2009-06-17 3 views
5

Я управляю тестированием для очень большой системы финансового ценообразования. Недавно наш штаб настаивал на том, что мы проверяем, что каждая часть нашего проекта имеет осмысленный тест. По крайней мере, им нужна система, которая гарантирует, что когда мы что-то изменим, мы можем обнаружить непреднамеренные изменения в других подсистемах. Предпочтительно они хотят что-то, что подтверждает правильность каждого компонента в нашей системе.Как сделать осмысленный анализ покрытия кода моих модульных тестов?

Это, очевидно, будет очень много работы! Это может занять годы, но для такого проекта это того стоит.

Мне нужно выяснить, какие части нашего кода не охватываются ни одним из наших модульных тестов. Если бы я знал, какие части моей системы были непроверены, я мог бы приступить к разработке новых тестов, которые в конечном итоге приблизились бы к моей цели полного тестирования.

Итак, как я могу запустить такой анализ. Какие инструменты доступны мне?

Я использую Python 2.4 на Windows 32bit XP

UPDATE0:

Просто уточнить: У нас есть очень обширный блок-тестов (плюс индивидуальный и всеобъемлющий regtest люкс, который находится вне сферы это упражнение). У нас также есть очень стабильная платформа непрерывной интеграции (построенная с помощью Hudson), которая предназначена для разделения и запуска стандартных модульных тестов python на нашем испытательном объекте: около 20 компьютеров построены для спецификации компании.

Целью этого упражнения является подключение любых пробелов в нашем наборе (только) набора для пула python, чтобы каждый компонент имел некоторую степень охвата unittest. Другие разработчики будут нести ответственность за компоненты, не входящие в состав Python проекта (которые также не входят в сферу охвата).

«Компонент» преднамеренно неопределенный: иногда это будет класс, в другое время - весь модуль или сборка модулей. Это может даже относиться к единой финансовой концепции (например, к одному типу финансового варианта или к финансовой модели, используемой многими вариантами). Этот торт можно разрезать по-разному.

«« Тесты (для меня) - это те, которые подтверждают, что функция выполняет то, что первоначально предполагал разработчик. Мы не хотим просто воспроизводить регесты в чистом питоне. Часто намерение разработчика не сразу очевидна, поэтому необходимо исследовать и прояснять все, что выглядит неопределенным, а затем закреплять это знание в единичном тесте, что делает первоначальное намерение совершенно явным.

ответ

6

Для покрытия кода можно использовать coverage.py.

Что касается coverage.py против figleaf:

фигового листка отличается от золотого стандарта инструментов покрытия Python ('coverage.py') несколькими способами. Прежде всего, фиговый листок использует же критерий для «интересных» линий кода как функция sys.settrace, который устраняет некоторые сложности в coverage.py (но это означает, что ваш «LOC» отсчет идет вниз). Во-вторых, figleaf не записывает выполненный код в стандартной библиотеке Python, которая значительно увеличивает скорость работы .И третий, формат, в котором сохраняется формат покрытия , очень прост и удобен в работе с .

Вы можете использовать фиговый листок, если вы записываете покрытие из нескольких видов испытаний и должен агрегировать покрытие в интересных путях, и/или управление, когда покрытие записано. coverage.py - лучший выбор для выполнения командной строки , а его отчет является более приятным.

Я думаю, что оба имеют свои плюсы и минусы.

+0

Спасибо за suggegstion: Зачем использовать это вместо фиолетового? –

+0

В ответ я добавил объяснение 'coverage.py vs figleaf'. Я не думаю, что это действительно важно, какой из них вы выберете. Справедливости ради, я не использовал ни одного из них, хотя это два основных инструмента. – Razzie

+2

охват3 устраняет множество предыдущих недостатков, то есть не выполняет stdlib и др. – Almad

1

Предполагая, что у вас уже есть относительно обширный набор тестов, есть инструменты для части python. Часть C намного более проблематична, в зависимости от доступности инструментов.

  • Для python unit tests

  • Для кода C, то трудно на многих платформах, потому что дргоЕ, код профайлер Gnu не может обрабатывать код, построенный с -fPIC. Поэтому в этом случае вам необходимо построить все расширения статически, что не поддерживается многими расширениями (см., Например, мой blog post for numpy). В окнах могут быть улучшены инструменты для покрытия кода для скомпилированного кода, но для этого может потребоваться перекомпиляция расширений с помощью компиляторов MS.

Что касается «правильного» покрытия кода, я считаю, что это хороший баланс, чтобы избежать написания сложных модульных тестов в максимально возможной степени. Если единичный тест более сложный, чем предмет, который он тестирует, то это, вероятно, не очень хороший тест или сломанный тест.

+0

Я только забочусь о Python - и да: у нас очень обширный набор тестов. –

+0

Степень сложности тестов зависит от того, что мы тестируем: некоторые нефинансовые классы могут быть довольно тривиально проверены, если у нас есть некоторые финансовые материалы, которые могут нуждаться в тестах, которые намного превышают проверяемую вещь: это причина в том, что существует так много интересных краевых дел, которые должны быть проверены. –

+1

Обоснование заключается в том, что если ваши тесты сложны, больше, чем код, вы начинаете испытывать свои модульные тесты. –

4

Первым шагом будет написание значащих тестов. Если вы будете писать тесты, предназначенные только для полного охвата, вы будете контрпродуктивными; это, вероятно, означает, что вы сосредоточитесь на деталях реализации устройства, а не на ожиданиях.

BTW, я бы использовал нос в качестве раструба unittest (http://somethingaboutorange.com/mrl/projects/nose/0.11.1/); это плагиновая система очень хороша и предоставляет вам возможность для покрытия (- с покрытием для покрытия Ned, - с фиолетовым для Titus one, поддержка покрытия 3 должна появиться), и вы можете написать plugisn для своей собственной системы сборки, слишком.

+0

Тесты уже существуют: это стандартная библиотека на 100% python unittest. –

+0

Figleaf кажется очень хорошим предложением: мне нравится тот факт, что он поставляется с базовым инструментом отчетности. Это может быть адаптировано для моих целей. –

+0

Ну, нос совместим со стандартными unittests, но у вас есть некоторые бесплатные функции (например, плагины, но лучше выбор теста). – Almad

3

«каждая отдельная часть нашего проекта имеет значимое испытание на месте»

«Часть» не определено. «Значимое» не определено. Это нормально, однако, так как он улучшается дальше.

«проверяет правильность каждого компонента в нашей системе»

«Компонент» является неопределенным. Но правильность определена, и мы можем назначить ряд альтернатив компоненту. Вы упоминаете только Python, поэтому я предполагаю, что весь проект является чистым Python.

  • Проверяет правильность каждого модуля.

  • Проверяет правильность каждого класса каждого модуля.

  • Проверяет правильность каждого метода каждого класса каждого модуля.

Вы не спрашивали о линии покрытия кода или охвате логического пути, что хорошо. Таким образом, безумие.

«гарантирует, что, когда мы что-то изменить, мы можем спот непреднамеренных изменений в другие подсистемы»

Это регрессионное тестирование. Это логическое следствие любой дисциплины тестирования единицы.

Вот что вы можете сделать.

  1. Перечислите каждый модуль. Создайте unittest для этого модуля, который является просто unittest.main(). Это должно быть быстрым - всего несколько дней.

  2. Напишите хороший сценарий uniteest верхнего уровня, который использует testLoader для всех модульных тестов в вашем каталоге тестов и запускает их через текстовый бегун. На данный момент у вас будет много файлов - по одному на модуль, но нет реальных тестовых случаев. Получение тестового загрузчика и скрипта верхнего уровня займет несколько дней. Важно, чтобы эта общая упряжь работала.

  3. Приоритет ваших модулей. Хорошее правило «наиболее сильно используется». Другое правило - «самый высокий риск от неудачи». Другое правило - «большинство ошибок». Это занимает несколько часов.

  4. Начало в верхней части списка. Напишите TestCase для каждого класса без каких-либо реальных методов или чего-либо еще. Просто рамки. Это занимает всего несколько дней. Убедитесь, что docstring для каждой TestCase положительно идентифицирует тестируемый модуль и класс и состояние тестового кода. Вы можете использовать эти docstrings для определения покрытия теста.

На этом этапе у вас будет две параллельные дорожки. Вы должны проектировать и выполнять тесты. В зависимости от тестируемого класса вам, возможно, придется создавать тестовые базы данных, макеты объектов и всевозможные вспомогательные материалы.

  • Испытание на восстановление. Начиная с вашего непроверенного модуля с наивысшим приоритетом, начните заполнять TestCases для каждого класса в каждом модуле.

  • Новые разработки. Для при каждом изменении кода необходимо изменить объект unittest.TestCase для изменяемого класса.

Код проверки соответствует тем же правилам, что и любой другой код. Все будет проверено в конце дня. Он должен работать, даже если тесты не все проходят.

Дайте тестовый сценарий менеджеру продукта (а не менеджеру QA, фактическому менеджеру по продуктам, который отвечает за доставку продукта клиентам) и убедитесь, что они запускают сценарий каждый день и выясняют, почему он не запускался или почему тесты терпят неудачу.

Фактический запуск сценария мастер-теста не является задачей QA - это работа каждого. Каждый менеджер на всех уровнях организации должен быть частью ежедневного выпуска скрипта сборки.Все их работы должны зависеть от «всех тестов, прошедших прошлой ночью». В противном случае менеджер продукта просто удалит ресурсы от тестирования, и у вас ничего не будет.

+0

Спасибо за ваши комментарии: Существует нулевая опасность того, что этот проект будет де-финансирован. Тестирование поручено высшим органам власти, и все в команде покупают его. Теоретически каждый нетривиальный класс ДОЛЖЕН иметь набор модульных тестов, посвященный некоторой форме проверки. Насколько «значимые» эти тесты различаются: например, простейшие тесты могут просто проверить, можно ли вызвать функцию и вернуть соответствующие типы. Более эффективные тесты могут проверять математические свойства возвращаемых данных. Очевидно, мы хотим большего от последнего. –

+0

Кроме того, у нас есть очень обширный набор модулей тестирования (плюс отдельный набор регестеров, который выходит за рамки этого упражнения). Целью этого упражнения является подключение любых пробелов в нашем наборе unittest (только), чтобы каждый компонент имел некоторую степень непроницаемости. «Компонент» преднамеренно неопределенен: иногда это будет класс, в другое время - весь модуль или сборка модулей. «Значимые» тесты (для меня) - это те, которые подтверждают, что функция выполняет то, что первоначально предполагал разработчик. Это потребует много исследований. –

+0

@Salim Fadhley: Пожалуйста, обновите вопрос этими дополнительными фактами. Совершенно очевидно, что у вас есть какие-либо тесты. –

4

FWIW, это то, что мы делаем. Поскольку я не знаю о вашей установке Unit-Test и Regression-Test, вы должны решить, насколько это полезно.

  • Каждый пакет Python имеет UnitTests.
  • Мы автоматически обнаруживаем модульные тесты с использованием nose. Нос автоматически обнаруживает стандартные тестовые тесты Python (в основном все, что looks like a test). Таким образом, мы не пропускаем единичные тесты. Нос также имеет концепцию подключаемого модуля, так что вы можете производить, например. хороший выход.
  • Мы стремимся к 100% -ному охвату для модульного тестирования. С этой целью мы используем Coverage , чтобы проверить, потому что a nose-plugin provides integration.
  • Мы создали Eclipse (наша IDE) до automatically run nose всякий раз, когда файл изменяется, так что модульные тесты всегда выполняются, что показывает покрытие кода как побочный продукт.
Смежные вопросы