Commited: 50+ воркшопів з ТОПами тестування: M.Bolton, G.Bahmutov, T.King, R.Desyatnikov, J.Bach. Лише за $40 на рік та економія $15 до 20 квітня
×Закрыть

Тестирование Python-приложений: от unittest к nose

С тех пор, как появилась первая библиотека для модульного тестирования — JUnit — появилась необходимость удобного выполнения тестов и представления результатов. В классическом JUnit были т.н. «runners», один для консоли, другой для графического режима. Современные Java-IDE обычно интегрируют процесс исполнения тестов обычно прямо в оболочку, благо в JUnit есть для этих целей API.

Когда в Python 2.1 появился модуль unittest его дизайн был фактически содран с JUnit, включая интерфейс нахождения тестов и TextRunner для выполнения тестов в консоли. Наверное любой Python-программист знаком с unittest.main(), assertEquals и unitest.TestCase. По крайней мере, у меня в Vim даже макросы есть специальные для набора этих повторяющихся конструкций.

Как это часто бывает с заимствованиями, удобство использования инструмента с «чуждой» идеологией оставляли желать лучшего. Одним не нравилось необходимость наследоваться от unitest.TestCase, другим — необходимость писать self.assertEquals() вместо привычного assert, третьим — негибкость в поиске и исполнении тестов.

В конце концов «терпець урвався» и на свет появилась первая реальная альтернатива unittest — py.test, как часть амбициозного проекта py lib. На мой взгляд, чересчур амбициозного, с невысокими шансами попасть в mainstream. Компонент py.test был и остается, пожалуй, самой популярной частью проекта.

Девиз py.test: «лучший API — его отсутствие». Как следствие, исчез класс TestCase от которого необходимо было наследоваться, вместе со своими assertEquals методами.
Наконец-то появилась возможность использовать обычный assert, а тесты определялись по наличию приставки test_ в именах функций и файлов.

Главных проблем с py.test было две: неудобство установки (требовался полный SVN checkout проекта py с последующими махинациями с PATH/PYTHONPATH) и «too much magic». Как я говорил, проект py был весьма «продвинутым» и использовал очень уж сомнительные «трюкачества» над интерпретатором. В результате иногда тесты не выполнялись или падали с какой-нибудь экзотической ошибкой.

Обе эти проблемы были решены при помощи nose. Эта поистине замечательная программка-кроха (<1,5KLoC) выполнена в лучших Unix-традициях: «do one thing and do it well». В двух словах это «py.test done right».

Магии в ней самый минимум, а устанавливается она при помощи сверх-удобной setuptools. В результате установки получаем скрипт «nosetests» который найдет и выполнит все наши тесты.

Помимо описанных выше функций, перешедших из py.test есть в ней и другие приятные мелочи, как-то: code coverage report (если установлен coverage.py), интеграция с doctest, «правильный» nosetest.main (оригинальный unittest.main использует sys.exit() что делает затруднительной интеграцию), package-level fixtures (определяются в __init__.py), интеграция с уже упомянутыми setuptools.

Собственно использование nose я решил оставить за рамками статьи т.к. документация описывает все что нужно.

P.S.: По большому счету, тестировать можно не только приложения написанные на Пайтоне, но практически это имеет смысл если Python уже используется каким-то образом. Например, когда тесты пишутся на Python, приложение на Си, а взаимодейстуют они через HTTP/командный интерфейс/API. Я, например, использую nose для тестирования веб-приложения при помощи twill.

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

👍НравитсяПонравилось0
В избранноеВ избранном0
Подписаться на автора
LinkedIn

Похожие статьи




Підписуйтесь: iTunes | Google Podcast | YouTube


4 комментария

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

Обалденная штука. Раньше пользовал py.test, это — лучше. Кстати, никто не писал под него тесты для twisted? Может, есть уже для плагин, повторяющий функциональность twisted.trial?

Насколько я знаю, эта опция мало на что влияет (помимо отключения ассертов) и соотв очень редко используется (во всяком случае я об этом не знаю). А насчет гейзенбагов в модульных тестах — это сильно сказано.:)

Это сильно сказано. А если нужно протестировать реальное поведение проги при этой опции? А еще есть гейзенбаги, я думаю вы о них знаете.

Ну так не надо запускать интерпретатор с опцией -О.;) Тем более для тестирования.

Подписаться на комментарии