Настройка правильного тестирования для Django для TDD - PullRequest
14 голосов
/ 11 февраля 2011


Я игнорировал необходимость тестировать мой проект на долгое время.

Таким образом, я потратил больше дня на поиск способов внедрения тестов для моих текущих приложений и на попытки запустить TDD для новых приложений.

Я нашел много «учебных пособий» со следующими шагами: «1. Установите это 2. Установите это 3. Установите это 4. Готово!»,
, но никто, кажется, не говорит о том, как структурировать ваштесты, как файловые, так и программные.

И никто никогда не говорит о том, как настроить CI-сервер или просто интегрировать тестирование с развертыванием вашего проекта.
Многие люди упоминают Fabric, virtualenvи нос - но никто не описывает, как они работают вместе с ними в целом.

Я постоянно нахожу подробные сведения о том, как вы настроили правильную среду Rails с тестированием, CI и т. д. ...

Кто-нибудь еще чувствует, что сообществу Джанго не хватает в этой области, или это только я?:)

О, а у кого-нибудь еще есть предложения, как это сделать?

Ответы [ 4 ]

8 голосов
/ 03 ноября 2011

На мой взгляд, проблема состоит из нескольких частей.

Одна вещь, которая вам нужна, это хорошие юнит-тесты. Основной характеристикой модульных тестов является то, что они очень быстрые, так что они могут тестировать комбинаторные возможности входов функций и покрытия ветвлений. Чтобы получить их скорость и поддерживать изоляцию между тестами, даже если они работают параллельно, модульные тесты не должны касаться базы данных, сети или файловой системы. Такие тесты трудно писать в проектах Django, потому что Django ORM делает его настолько удобным, чтобы распределять вызовы доступа к базе данных по всему коду вашего продукта. Следовательно, любые тесты кода Django неизбежно попадут в базу данных. В идеале вам следует подходить к этому, ограничивая доступ к базе данных в коде своего продукта тонким слоем доступа к данным, построенным поверх ORM django, который предоставляет методы, подходящие для вашего приложения. Другой подход заключается в том, что ваши тесты макетируют вызовы ORM. В худшем случае вы откажетесь от этого: ваши модульные тесты станут интеграционными тестами: они фактически попадают в базу данных, пересекают несколько уровней вашей архитектуры и требуют нескольких минут для запуска, что не позволяет разработчикам запускать их достаточно часто.

Смысл этого в том, что написание интеграционных тестов легко - канонический стиль тестов Django прекрасно это охватывает.

Последняя и самая сложная часть проблемы - запуск приемочных тестов. Определяющей характеристикой приемочных тестов является то, что они вызывают ваше приложение сквозным, как пользователь делает в производстве, чтобы доказать, что ваше приложение действительно работает. Канонические тесты dhango с использованием тестера django не соответствуют этому. На самом деле они не выдают HTTP-запросы (вместо этого они изучают конфигурацию URL-адреса, чтобы выяснить, какое промежуточное программное обеспечение и представление будут вызываться для обработки определенного запроса, а затем они вызывают его в процессе.) Это означает, что такие тесты не проверяют ваши Конфигурация веб-сервера, ни какой-либо JavaScript, или рендеринг в браузере, и т. д. Чтобы проверить это, вам нужно что-то вроде селен.

Кроме того, у нас есть много серверных процессов, таких как задания cron, которые используют код из нашего проекта Django. Приемочные тесты, в которых задействованы эти процессы, должны запускать задания так же, как и cron, как новый процесс.

В обоих этих сценариях есть некоторые проблемы. Во-первых, вы не можете просто запускать такие тесты под Django. Если вы попытаетесь сделать это, то обнаружите, что тестовые данные, которые вы записали во время настройки теста (либо с помощью механизма фикстур django, либо просто вызвав «MyModel (). Save ()» в тесте), находятся в транзакция, к которой не относится ваш код продукта, запущенный в другом процессе. Таким образом, ваши тесты должны зафиксировать внесенные изменения, прежде чем код продукта сможет их увидеть. Это мешает очистке между тестами, которую усложняет тест-запускщик Django, поэтому вы должны переключить его в другой режим, который выполняет явное удаление, а не откат. К сожалению, это намного медленнее. В прошлой ночи в лондонской группе пользователей Django пара разработчиков ядра Django заверили меня, что у этого сценария есть и другие сложности (которые, признаюсь, я не знаю, каковы они есть), которых лучше избегать, не проводя приемочные тесты в рамках Django - тестовый бегун вообще, но создает их как полностью автономный набор тестов.

Если вы сделаете это, то ваша непосредственная проблема заключается в том, что вы утратили преимущества, предоставляемые тестовым исполнителем Django: именно он создает тестовую базу данных и очищает ее между каждым тестом. Вам придется создать какой-то эквивалентный механизм для себя. Вам потребуется код вашего продукта для запуска в тестовой базе данных, если он вызывается как часть теста. Вы должны быть абсолютно уверены в том, что если код продукта запускается как часть теста, даже в рабочей коробке, он НИКОГДА не может случайно коснуться рабочей базы данных, поэтому этот механизм должен быть абсолютно отказоустойчивым. Например, если вы забудете установить переменную среды в тестовой настройке, это не должно привести к блокировке.

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

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

5 голосов
/ 03 ноября 2011

Гарри Персиваль создает учебник по Django / TDD / Selenium (и сопровождающий семинар, если вы живете в Лондоне). Его книга читается как практическое пособие и подробно описывает предмет:

https://www.obeythetestinggoat.com/book/part1.harry.html

3 голосов
/ 14 февраля 2011

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

У меня был лучший опыт тестирования с использованием полуфункционального инструмента тестирования под названием testbrowser , который имитирует действия браузера в Python.Для интеграции с Django установите приложение homophony (отказ от ответственности: я являюсь автором приложения).

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

Что касается инструмента CI, используйте Buildbot или Jenkins.

0 голосов
/ 20 февраля 2011

Я использую комбинацию превосходного расширения Django платформы python unittest для тестирования функций api / models / helper и selenium для тестирования браузера. У Selenium есть отличные инструкции по настройке и написанию тестов на python.

...