Написание и запуск тестов ¶
Смотрите также
Тестирования учебник , то инструменты тестирования ссылки , и сложные темы тестирования .
Этот документ разделен на два основных раздела. Сначала мы объясним, как писать тесты с помощью Django. Затем мы объясняем, как их запускать.
Написание тестов ¶
Модульные тесты Django используют стандартный модуль библиотеки Python: unittest
. Этот модуль определяет тесты с использованием подхода на основе классов.
Вот пример, от которого подклассы django.test.TestCase
, который является подклассом, unittest.TestCase
который запускает каждый тест внутри транзакции, чтобы обеспечить изоляцию:
from django.test import TestCase
from myapp.models import Animal
class AnimalTestCase(TestCase):
def setUp(self):
Animal.objects.create(name="lion", sound="roar")
Animal.objects.create(name="cat", sound="meow")
def test_animals_can_speak(self):
"""Animals that can speak are correctly identified"""
lion = Animal.objects.get(name="lion")
cat = Animal.objects.get(name="cat")
self.assertEqual(lion.speak(), 'The lion says "roar"')
self.assertEqual(cat.speak(), 'The cat says "meow"')
Когда вы запускаете свои тесты , поведение тестовой утилиты по умолчанию заключается в том, чтобы найти все тестовые примеры (то есть подклассы
unittest.TestCase
) в любом файле, имя которого начинается с test
, автоматически построить набор тестов из этих тестовых примеров и запустить этот набор. .
Дополнительные сведения unittest
см. В документации Python.
Где должны жить тесты?
startapp
Шаблон по умолчанию создает tests.py
файл в новом приложении. Это может быть хорошо , если у вас есть только несколько тестов, но , как ваш набор тестов растет вы , вероятно , хотите , чтобы реструктурировать его в пакет тестов , так что вы можете разделить ваши тесты в различные подмодули , такие как
test_models.py
, test_views.py
, test_forms.py
и т.д. Не стесняйтесь , чтобы выбрать какая бы организационная схема вам ни нравилась.
См. Также Использование средства запуска тестов Django для тестирования приложений многократного использования .
Предупреждение
Если ваши тесты полагаются на доступ к базе данных, такой как создание или запрос моделей, обязательно создавайте свои тестовые классы как подклассы,
django.test.TestCase
а не unittest.TestCase
.
Использование unittest.TestCase
позволяет избежать затрат на запуск каждого теста в транзакции и очистку базы данных, но если ваши тесты взаимодействуют с базой данных, их поведение будет зависеть от порядка, в котором их выполняет исполнитель тестов. Это может привести к тому, что модульные тесты пройдут изолированно, но не пройдут в комплекте.
Запуск тестов ¶
После того, как вы написали тесты, запустите их, используя test
команду manage.py
утилиты вашего проекта :
$ ./manage.py test
Обнаружение тестов основано на обнаружении тестов, встроенных в модуль unittest . По умолчанию это обнаружит тесты в любом файле с именем «test * .py» в текущем рабочем каталоге.
Вы можете указать конкретные тесты для запуска, предоставив им любое количество «тестовых меток» . Каждая тестовая метка может быть полным пунктирным путем Python к пакету, модулю, подклассу или методу тестирования. Например:./manage.py test
TestCase
# Run all the tests in the animals.tests module
$ ./manage.py test animals.tests
# Run all the tests found within the 'animals' package
$ ./manage.py test animals
# Run just one test case
$ ./manage.py test animals.tests.AnimalTestCase
# Run just one test method
$ ./manage.py test animals.tests.AnimalTestCase.test_animals_can_speak
Вы также можете указать путь к каталогу для обнаружения тестов под этим каталогом:
$ ./manage.py test animals/
Вы можете указать собственное совпадение с шаблоном имени файла с помощью опции -p
(или
--pattern
), если ваши тестовые файлы имеют имена, отличные от
test*.py
шаблона:
$ ./manage.py test --pattern="tests_*.py"
Если вы нажмете Ctrl-C
во время выполнения тестов, средство запуска тестов будет ждать завершения текущего выполняемого теста и затем корректно завершит работу. Во время плавного выхода средство выполнения тестов выведет подробную информацию о любых сбоях теста, сообщит о том, сколько тестов было выполнено и сколько ошибок и сбоев было обнаружено, и уничтожит все тестовые базы данных как обычно. Таким образом, нажатие
Ctrl-C
может быть очень полезным, если вы забыли передать --failfast
опцию, заметили, что некоторые тесты неожиданно завершаются сбоем, и хотите получить подробную информацию о сбоях, не дожидаясь завершения полного тестового прогона.
Если вы не хотите ждать завершения текущего запущенного теста, вы можете нажать Ctrl-C
второй раз, и тестовый запуск будет немедленно остановлен, но не изящно. Никаких подробностей о тестах, запущенных до прерывания, не будет сообщаться, и все тестовые базы данных, созданные в ходе выполнения, не будут уничтожены.
Тест с включенными предупреждениями
Это хорошая идея , чтобы запустить тесты с предупреждениями Python включен:
. Флаг говорит Python для отображения устаревания предупреждения. Django, как и многие другие библиотеки Python, использует эти предупреждения, чтобы сигнализировать об отключении функций. Он также может отмечать области в вашем коде, которые не являются строго неправильными, но могут выиграть от лучшей реализации.python -Wa manage.py test
-Wa
Тестовая база данных ¶
Тесты, для которых требуется база данных (а именно, модельные тесты), не будут использовать вашу «настоящую» (производственную) базу данных. Для тестов создаются отдельные пустые базы данных.
Независимо от того, пройдены ли тесты или нет, тестовые базы данных уничтожаются после выполнения всех тестов.
Вы можете предотвратить уничтожение тестовых баз данных, используя
опцию. Это сохранит тестовую базу данных между запусками. Если база данных не существует, она сначала будет создана. Любые миграции также будут применяться, чтобы поддерживать его в актуальном состоянии.test --keepdb
Как описано в предыдущем разделе, если тестовый запуск принудительно прерван, тестовая база данных не может быть уничтожена. При следующем запуске вас спросят, хотите ли вы повторно использовать или уничтожить базу данных. Используйте параметр, чтобы подавить этот запрос и автоматически уничтожить базу данных. Это может быть полезно при запуске тестов на сервере непрерывной интеграции, где тесты могут быть прерваны, например, из-за тайм-аута.test
--noinput
Имена тестовых баз данных по умолчанию создаются путем добавления test_
значений каждого NAME
в DATABASES
. При использовании SQLite тесты по умолчанию будут использовать базу данных в памяти (т. Е. База данных будет создана в памяти, полностью минуя файловую систему!). TEST
Словарь в DATABASES
предложениях ряда параметров для настройки тестовой базы данных. Например, если вы хотите использовать другое имя базы данных, укажите NAME
в TEST
словаре любую базу данных в формате DATABASES
.
В PostgreSQL USER
также потребуется доступ для чтения к встроенной
postgres
базе данных.
Помимо использования отдельной базы данных, тест бегун будет иным образом использовать все ту же настройку базы данных вы имеете в файле настройки:
ENGINE
, USER
, HOST
и т.д. Тестовая база данных создаются пользователем указанного USER
, так что вам нужно , чтобы убедиться , что данная учетная запись пользователя имеет достаточные права для создания новой базы данных в системе.
Для точного управления кодировкой символов в тестовой базе данных используйте параметр CHARSET
TEST. Если вы используете MySQL, вы также можете использовать COLLATION
опцию для управления конкретным сопоставлением, используемым тестовой базой данных. См.
Документацию по настройкам для получения подробной информации об этих и других дополнительных настройках.
При использовании базы данных SQLite в памяти с SQLite общий кеш включен, поэтому вы можете писать тесты с возможностью совместного использования базы данных между потоками.
Находите данные из производственной базы данных при запуске тестов?
Если ваш код пытается получить доступ к базе данных при компиляции ее модулей, это произойдет до того, как будет настроена тестовая база данных, с потенциально неожиданными результатами. Например, если у вас есть запрос к базе данных в коде уровня модуля и существует реальная база данных, производственные данные могут загрязнить ваши тесты. В любом случае иметь в коде такие запросы к базе данных во время импорта - плохая идея - перепишите код так, чтобы он этого не делал.
Это также относится к индивидуальным реализациям
ready()
.
Смотрите также
Порядок выполнения тестов ¶
Чтобы гарантировать, что весь TestCase
код начинается с чистой базы данных, средство запуска тестов Django переупорядочивает тесты следующим образом:
- Все
TestCase
подклассы запускаются первыми. - Затем все другие тесты на основе Django (в
SimpleTestCase
том числе тестовые примерыTransactionTestCase
) запускаются без какого-либо гарантированного или принудительного упорядочивания среди них. - Затем
unittest.TestCase
запускаются любые другие тесты (включая doctest), которые могут изменить базу данных без восстановления ее исходного состояния.
Примечание
Новый порядок тестов может выявить неожиданные зависимости от порядка тестов. Так обстоит дело с тестами, которые основаны на состоянии, оставленном в базе данных данным TransactionTestCase
тестом, они должны быть обновлены, чтобы иметь возможность работать независимо.
Вы можете изменить порядок выполнения внутри групп, используя опцию. Это может помочь обеспечить независимость ваших тестов друг от друга.test
--reverse
Эмуляция отката ¶
Любые исходные данные, загруженные при миграции, будут доступны только в TestCase
тестах, но не в TransactionTestCase
тестах, и, кроме того, только в бэкэндах, где поддерживаются транзакции (наиболее важным исключением является MyISAM). Это также верно для тестов, которые полагаются на TransactionTestCase
такие как LiveServerTestCase
и
StaticLiveServerTestCase
.
Django может перезагружать эти данные для каждого тестового набора, установив serialized_rollback
параметр True
в теле
TestCase
или TransactionTestCase
, но учтите, что это замедлит этот набор тестов примерно в 3 раза.
Сторонние приложения или приложения, разработанные для MyISAM, должны будут это установить; в целом, однако, вы должны разрабатывать свои собственные проекты для транзакционной базы данных и использовать их TestCase
для большинства тестов, и поэтому этот параметр не нужен.
Первоначальная сериализация обычно выполняется очень быстро, но если вы хотите исключить некоторые приложения из этого процесса (и немного ускорить выполнение тестов), вы можете добавить эти приложения в TEST_NON_SERIALIZED_APPS
.
Чтобы сериализованные данные не загружались дважды, этот параметр
serialized_rollback=True
отключает
post_migrate
сигнал при очистке тестовой базы данных.
Другие условия испытаний ¶
Независимо от значения DEBUG
параметра в вашем файле конфигурации, все тесты Django запускаются с DEBUG
= False. Это необходимо для того, чтобы наблюдаемый вывод вашего кода соответствовал тому, что будет видно в производственной настройке.
Кеши не очищаются после каждого теста, и запуск «manage.py test fooapp» может вставлять данные из тестов в кеш действующей системы, если вы запускаете тесты в производственной среде, потому что, в отличие от баз данных, отдельный «тестовый кеш» не работает. использовал. Это поведение может измениться в будущем.
Понимание результатов теста ¶
Когда вы запустите свои тесты, вы увидите ряд сообщений по мере того, как средство запуска тестов готовится. Вы можете контролировать уровень детализации этих сообщений с помощью
verbosity
параметра в командной строке:
Creating test database...
Creating table myapp_animal
Creating table myapp_mineral
Это говорит о том, что средство запуска тестов создает тестовую базу данных, как описано в предыдущем разделе.
После создания тестовой базы данных Django выполнит ваши тесты. Если все пойдет хорошо, вы увидите что-то вроде этого:
----------------------------------------------------------------------
Ran 22 tests in 0.221s
OK
Однако, если есть сбои тестов, вы увидите полную информацию о том, какие тесты не прошли:
======================================================================
FAIL: test_was_published_recently_with_future_poll (polls.tests.PollMethodTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/dev/mysite/polls/tests.py", line 16, in test_was_published_recently_with_future_poll
self.assertIs(future_poll.was_published_recently(), False)
AssertionError: True is not False
----------------------------------------------------------------------
Ran 1 test in 0.003s
FAILED (failures=1)
Полное объяснение этого вывода ошибки выходит за рамки этого документа, но оно довольно интуитивно понятно. Вы можете обратиться к документации unittest
библиотеки Python
за подробностями.
Обратите внимание, что код возврата для сценария запуска тестов - 1 для любого количества неудачных и ошибочных тестов. Если все тесты пройдены, код возврата равен 0. Эта функция полезна, если вы используете сценарий запуска тестов в сценарии оболочки и вам нужно проверить успешность или неудачу на этом уровне.
Ускорение тестов ¶
Параллельное выполнение тестов ¶
Пока ваши тесты должным образом изолированы, вы можете запускать их параллельно, чтобы ускорить работу на многоядерном оборудовании. Смотрите .test --parallel
Хеширование паролей ¶
Хэширование паролей по умолчанию довольно медленное по дизайну. Если вы аутентифицируете много пользователей в своих тестах, вы можете использовать файл пользовательских настроек и PASSWORD_HASHERS
установить более быстрый алгоритм хеширования:
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.MD5PasswordHasher',
]
Не забудьте также включить в PASSWORD_HASHERS
любой алгоритм хеширования, используемый в фикстурах, если таковые имеются.
Сохранение тестовой базы ¶
Эта опция сохраняет тестовую базу данных между тестовыми запусками. Он пропускает действия создания и уничтожения, что может значительно сократить время выполнения тестов.test --keepdb