RU | EN

Покрытие кода тестами

Юнит-тесты хороши, когда покрывают весь ключевой код. Однако если проект чуть больше, чем “Hello, world!”, то оценить степень покрытия весьма проблематично. Существуют инструменты, которые помогают это делать. Для Python я знаю два таких:

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

twisted.trial

У команды trial есть опция coverage, после выполнения всех тестов во временном каталоге тестов появляется информация о покрытии кода тестами (по умолчанию искать нужно в _trial_temp/coverage). Имена файлов имеют вид package_name.module_name.cover. Каждый файл содержит строчки кода и счетчик, сколько раз каждая строка была выполнена. Ни разу не выполненные строки помечаются маркером >>>>>>.
Т.е. никаких количественных оценок twisted.trial не дает, лишь визуально выделяет непротестированные участки кода. Правда, получить количественные оценки по этим результатам достаточно просто (достаточно подсчитать общее количество “помеченных” и “посчитанных” строк и взять от этого количества процентное соотношение к “помеченным”), странно что это не сделали разработчики. Еще один минус, который хочу отметить - необходимо использовать twisted.trial, а не unittest (т.е. во всех модулях юнит-тестов заменить import unittest на from twisted.trial import unittest). Ну и ставить целиком Twisted (а trial является его неразрывным компонентом) только ради того, чтобы померить покрытие кода, нецелесообразно.

coverage.py

coverage.py является более адекватным инструментом - ни от каких дополнительных библиотек он не зависит, может использоваться как из командной строки, так и из кода (как библиотека). Плюс к этому, он может выдавать как суммарный результат (в процентах), так и анотированный (т.е. копия исходного файла, в котором протестированная строка помечается >, не протестированная - !). В общем, must have. Ниже приведу пару советов по использованию.

Из командной строки

Первый шаг - собирается информация по ходу выполнения юнит-тестов, собранная информация сохраняется в файле .coverage текущего каталога. Если ранее coverage.py уже запускался, то лучше сбросить ранее сохраненные данные (ключ -e)

$ coverage.py -e $ coverage.py -x /path/to/unit/test_module.py

Второй шаг - по полученной информации создается суммарный отчет для указанного файла

$ coverage.py -r -m /path/to/module.py

Если же хочется получить анотированный отчет, то для этого служит опция -a:

$ coverage.py -a /path/to/module.py

и после этого, рядом с module.py появляется анотированный module.py,cover
Ну и “живой” пример с PyTils:

$ coverage.py -e $ coverage.py -x /usr/local/lib/python2.4/site-packages/pytils/test/__init__.py testChoosePlural (pytils.test.test_numeral.ChoosePluralTestCase) ... ok [...] testProvideUnicode (pytils.test.test_utils.UnicodeTestCase) ... ok ---------------------------------------------------------------------- Ran 36 tests in 0.252s OK $ coverage.py -r -m /usr/local/lib/python2.4/site-packages/pytils/numeral.py Name Stmts Exec Cover Missing ------------------------------------------------------------------------------------- /usr/local/lib/python2.4/site-packages/pytils/numeral 138 136 98% 340, 365

Из кода

Использовать coverage.py из кода даже проще, чем из командной строки:

>>> import coverage >>> coverage.erase() >>> coverage.start() >>> import yourmodule >>> youmodule.test.run() >>> coverage.stop() >>> coverage.report([yourmodule.foo, yourmodule.bar])

и живой пример:

>>> import coverage >>> coverage.erase() >>> coverage.start() >>> import pytils >>> pytils.VERSION '0.1.0-svn20061002' >>> pytils.test.run() .................................... ---------------------------------------------------------------------- Ran 36 tests in 0.207s OK >>> coverage.stop() >>> coverage.report([pytils.dt, pytils.numeral, pytils.translit, pytils.utils]) Name Stmts Exec Cover Missing ----------------------------------------------- pytils.dt 85 85 100% pytils.numeral 138 136 98% 340, 365 pytils.translit 38 37 97% 197 pytils.utils 34 32 94% 28-29 ----------------------------------------------- TOTAL 295 290 98%

P.S. Нед говорит, что еще есть pycover и что в Sancho тоже можно покрытие кода померять, но я ни тот, ни другой не пробовал.

Источники:
gorod-omsk.ru/blog/pythy/

Комментарии: