На мой взгляд, проблема состоит из нескольких частей.
Одна вещь, которая вам нужна, это хорошие юнит-тесты. Основной характеристикой модульных тестов является то, что они очень быстрые, так что они могут тестировать комбинаторные возможности входов функций и покрытия ветвлений. Чтобы получить их скорость и поддерживать изоляцию между тестами, даже если они работают параллельно, модульные тесты не должны касаться базы данных, сети или файловой системы. Такие тесты трудно писать в проектах 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, и т. Д.
В общем, я хотел бы услышать от кого-то, кто чувствует, что они нашли хорошее решение этой проблемы. Это далеко не тривиальный вопрос, как предполагают некоторые комментаторы.