разработка мобильных приложений, веб-сервисов и корпоративных систем
ru en
+7 (812) 324-27-24, +7 (495) 641-87-24
Заказать звонок

Усовершенствования в тестировании Django

В рамках серии переводов с DjangoAdvent, мы перевели статью Эрика Холшера «Django testing improvements».

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

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

Несколько баз данных

Что изменилось

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

Разработчикам Django

Для прохождения тестов Django теперь требуется более детальный файл установочных параметров. Если вы запустите набор тестов со старым файлом установочных параметров, который определял единственную базу данных, тесты MultiDB будут провалены (если быть точным, то 22 из них). Пример необходимого минимального файла установочных параметров представлен ниже. Что касается спринта Django Pycon, этот файл на самом деле поставляется непосредственно вместе Django. Поэтому для запуска набора тестов Django на SQLite вам не придётся трогать файловую систему!

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
},
'other': {
'ENGINE': 'django.db.backends.sqlite3',
'TEST_NAME': 'other_db',
}
}

Для запуска тестов перейдите в каталог tests вашей рабочей копии Django и выполните следующую команду:

./runtests.py --settings=test_sqlite

Вместе с этим запустится файл test_sqlite.py, который идентичен упомянутому выше файлу установочных параметров.

Разработчикам приложений

Если ожидается, что ваше приложение будет развёрнуто в среде нескольких баз данных, то вам действительно необходимо знать следующее. В документации Django по тестированию имеются отдельные темы по настойкам Testing Master/Slave, что позволяет использовать установку TEST_MIRROR на ведомой базе данных, чтобы она отражала ведущую базу данных для тестов. Django TestCase также добавил атрибут multidb, который очистит все базы данных до того как запустить внутри контрольные примеры. Стандартно, в качестве оптимизации Django очищает только базу данных по умолчанию.

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

Чем быстрее, тем лучше

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

Что изменилось

Что касается обновлений 11843, то Django добавил в тест раннер опцию --failfast. При выборе этой опции, Django прекратит тестирование, как только столкнётся с ошибкой. Это может быть полезным при определённых рабочих процессах, включая некоторые TTD, где вы часто ожидаете, что будет не пройден, и не хотите проходить всё тестирование для обнаружения того, что именно не прошло.

В Django 1.1 и более ранних версиях, при нажатии и отмене тестирования, вы бы получили трассировку без информации.

............^CTraceback (most recent call last):
File "./manage.py", line 11, in <module>
execute_manager(settings)
File "/Users/eric/svn-clones/django/template/__init__.py", line 285, in parse
compiled_result = compile_func(self, token)
KeyboardInterrupt

Если попробовать тот же трюк с обновлениями 12034, текущий тест будет изящно остановлен и завершён.

.....................^C <Test run halted by Ctrl-C> .
--------------------------------------------------------
Ran 22 tests in 1.308s
OK

Это позволяет вам получать те же преимущества от опции --failfast, даже если вы забыли задать её в самом начале. Как только вы увидите, что тест не пройден, вы можете просто нажать Ctrl+C и вернуть результат непройденного теста.

Разработчикам Django

Следующая информация важна при условиях разработки в дереве кода Django, потому что на запуск тестового набора Django требуется много времени. Полный набор может занять до 10 минут, особенно в случае с такими большими базами данных, как Oracle. Раньше, если вы видели проблему, вам бы пришлось ждать до окончания тестирования, чтобы обнаружить конкретную ошибку. Если прервать процесс, можно было бы потерять все данные! Сейчас же вы можете легко «соскочить» при первой проблеме, ну, а если вы забыли об опции --failfast, простая комбинация Ctrl+C сделает всё за вас.

Разработчикам приложений

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

Добавление аргумента --failfast к любому имеющемуся механизму для запуска тестов после изменений позволит вам работать быстрее, когда есть какие-то неполадки. Вы сразу получите уведомление об ошибках в коде и в тот же момент сможете их исправить.

Существуют и другие функциональности, которые также неплохо было бы иметь в этой области. Другая оптимизация заключается в возможности запускать полный тестовый набор, а потом запускать только проваленные в прошлый раз тесты. Надеемся, что эта возможность появится в Django 1.3 или ещё раньше будет выпущена как отдельное приложение.

Также имеют место некоторые попытки по интеграции ваших Django тестов с nose. Так что, если вы не начали писать свой набор тестов, просмотр django-nose и django-sane-testing будет полезен, так как nose уже имеет достаточно встроенных функциональностей.

Классы

Вероятно самое большое усовершенствование в инфраструктуре тестирования версии Django 1.2 – это тест раннеры на основе классов. Главное преимущество этого обновления состоит в том, что оно позволяет создавать подклассы текущего тест раннера. Таким образом, любому, кто хочет изменить ход тестирования Django, будет гораздо проще это сделать.

Что изменилось

Что касается обновлений 12255, то тест раннер по умолчанию для Django теперь является классом. Существует код, который будет определять, пытаетесь ли вы пройти в раннер, основанный на функции стиля 1.1, и действовать соответственно. Тем не менее, вам следует попробовать обновить кастомные тест раннеры в соответствии с новым стилем, так как в результате вы получите меньше кода и больше возможностей для обслуживания.

В действительности это применимо только к разработчикам приложений, потому что, если вы запускаете набор тестов Django, вы должны использовать официальный тест раннер Django.

Пример

В моем проекте Pony Utils я хотел создать свой собственный тест раннер и предварительную версию 1.2, на что мне потребовалось скопировать 60 строк кода, чтобы отредактировать только некоторые (строку 60). Функция run_tests в Django сейчас занимает 7 строк кода, что отсылает к другим методам. Эти другие методы легче классифицировать в своём тест раннере, замещая только части необходимые для достижения желаемого поведения.

Разница между новым и старым показывает изменённые строки кода. Однако на самом деле это следует делать в функции suite_result в классе тест раннера, так как я только хочу модифицировать отсылку тестовых результатов. Таким образом, видно, где дизайн можно усовершенствовать.

Раннему «джангонавту» везёт

Тестирование предварительного программного обеспечения даёт пользователям возможность обнаружить баги и найти случаи использования, о которых основные разработчики и не задумывались, а также сообщить о них до того, как они попадут в конечную версию, которая должна поддерживаться. Если какую-то новую функциональность не протестировать до выпуска, Django не будет поддерживать её как минимум три последующие версии, и все получат субоптимальное поведение.

Когда я писал эту статью, я нашёл способ лучшего использования нового тест раннера, основанного на классах. Функция тест раннера suite_result провалила тест, при этом результаты были включены в отчёт. По умолчанию в пределах функциональности Django – всего лишь сообщить о количестве ошибок и выйти, но я хотел большего и поэтому мне нужен был набор. Таким образом, несмотря на то, что мой пример использования не поддерживался, я заполнил форму и стал надеяться на лучшее.

К счастью, это произошло во время спринтов Pycon, и Расселл Кет-Меги принял форму и залатал Django всего за день! Этот случай является ярким примером того, как использование предварительной версии Django может помочь улучшить программное обеспечение.

Благодарю за прочтение

Я надеюсь, что из этой статьи вы узнали много интересного о тестировании и о новых функциональностях версии 1.2. Теперь смело приступайте к их использованию для усовершенствования качества вашего кода и самого Django!

Добавить комментарий