Модульные тесты ¶
Django поставляется с собственным набором тестов в tests
каталоге базы кода. Наша политика - обеспечить постоянное прохождение всех тестов.
Мы ценим любой вклад в набор тестов!
Все тесты Django используют инфраструктуру тестирования, которая поставляется с Django для тестирования приложений. См. Раздел Написание и выполнение тестов для объяснения того, как писать новые тесты.
Запуск модульных тестов ¶
Быстрый старт ¶
Сначала создайте вилку Django на GitHub .
Во-вторых, создайте и активируйте виртуальную среду. Если вы не знаете, как это сделать, прочтите наше дополнительное руководство .
Затем клонируйте вилку, установите некоторые требования и запустите тесты:
$ git clone https://github.com/YourGitHubName/django.git django-repo
$ cd django-repo/tests
$ python -m pip install -e ..
$ python -m pip install -r requirements/py3.txt
$ ./runtests.py
... \> git clone https://github.com/YourGitHubName/django.git django-repo
... \> cd django-repo \ tests
... \> py -m pip install -e ..
.. . \> py -m pip install -r требования \ py3.txt
... \> runtests.py
Для установки требований, скорее всего, потребуются некоторые пакеты операционной системы, которые не установлены на вашем компьютере. Обычно вы можете определить, какой пакет установить, выполнив поиск в Интернете по последней строке или около того в сообщении об ошибке. При необходимости попробуйте добавить свою операционную систему в поисковый запрос.
Если у вас возникли проблемы с установкой требований, вы можете пропустить этот шаг. См. Раздел Выполнение всех тестов для получения подробной информации об установке дополнительных тестовых зависимостей. Если у вас не установлена дополнительная зависимость, тесты, требующие ее, будут пропущены.
Для запуска тестов требуется модуль настроек Django, который определяет используемые базы данных. Чтобы помочь вам начать работу, Django предоставляет и использует образец модуля настроек, который использует базу данных SQLite. См. Раздел Использование другого модуля настроек, чтобы узнать, как использовать другой модуль настроек для запуска тестов с другой базой данных.
Возникли проблемы? См. Раздел « Устранение неполадок» для ознакомления с некоторыми распространенными проблемами.
Запуск тестов с использованием tox
¶
Tox - это инструмент для запуска тестов в различных виртуальных средах. Django включает базовый пакет, tox.ini
который автоматизирует некоторые проверки, которые наш сервер сборки выполняет при запросах на вытягивание. Чтобы запустить модульные тесты и другие проверки (например, сортировку импорта , проверку орфографии в
документации и
форматирование кода ), установите и запустите tox
команду из любого места в дереве исходного кода Django:
$ python -m pip install tox
$ tox
... \> py -m pip install tox
... \> tox
По умолчанию, tox
запускает набор тестов с помощью прилагаемого Тестировать настройки файла для SQLite, flake8
, isort
, и документация проверки орфографии. В дополнение к системным зависимостям, указанным в другом месте в этой документации, команда python3
должна быть на вашем пути и связана с соответствующей версией Python. Список сред по умолчанию можно увидеть следующим образом:
$ tox -l
py3
flake8
docs
isort>=5.1.0
... \> tox
-l
py3 flake8
документы
isort> = 5.1.0
Тестирование других версий Python и бэкендов баз данных ¶
В дополнение к средам по умолчанию tox
поддерживает выполнение модульных тестов для других версий Python и других баз данных. Поскольку набор тестов Django не объединяет файл настроек для серверной части базы данных, кроме SQLite, вы должны создать и предоставить свои собственные настройки теста . Например, чтобы запустить тесты на Python 3.7 с использованием PostgreSQL:
$ tox -e py37-postgres -- --settings=my_postgres_settings
...\> tox -e py37-postgres -- --settings=my_postgres_settings
Эта команда настраивает виртуальную среду Python 3.7, устанавливает зависимости набора тестов Django (в том числе для PostgreSQL) и вызывает
runtests.py
с предоставленными аргументами (в данном случае
--settings=my_postgres_settings
).
В оставшейся части этой документации показаны команды для запуска тестов без
tox
, однако, любой параметр, переданный в, runtests.py
также можно передать
tox
, добавив к списку аргументов префикс --
, как указано выше.
Tox также уважает DJANGO_SETTINGS_MODULE
переменная окружения, если установлена. Например, следующая команда эквивалентна приведенной выше команде:
$ DJANGO_SETTINGS_MODULE=my_postgres_settings tox -e py35-postgres
Пользователи Windows должны использовать:
...\> set DJANGO_SETTINGS_MODULE=my_postgres_settings
...\> tox -e py35-postgres
Запуск тестов JavaScript ¶
Django включает набор модульных тестов JavaScript для функций в определенных приложениях contrib. По умолчанию тесты JavaScript не запускаются, tox
потому что они требуют Node.js
установки и не нужны для большинства исправлений. Чтобы запустить тесты JavaScript, используйте
tox
:
$ tox -e javascript
...\> tox -e javascript
Эта команда запускается, чтобы убедиться, что требования к тестам актуальны, а затем запускается .npm install
npm test
Запуск тестов с использованием django-docker-box
¶
django-docker-box позволяет запускать набор тестов Django для всех поддерживаемых баз данных и версий Python. См. Страницу проекта django-docker-box для получения инструкций по установке и использованию.
Использование другого settings
модуля ¶
Включенный модуль настроек ( tests/test_sqlite.py
) позволяет запускать набор тестов с помощью SQLite. Если вы хотите запустить тесты с использованием другой базы данных, вам нужно будет определить свой собственный файл настроек. Некоторые тесты, такие как тесты, contrib.postgres
относятся к конкретной серверной части базы данных и будут пропущены при запуске с другой серверной частью.
Чтобы запустить тесты с разными настройками, убедитесь, что модуль установлен на вашем
PYTHONPATH
и передайте модуль с помощью --settings
.
Параметр DATABASES
в любом модуле настроек теста должен определять две базы данных:
default
Базы данных. Эта база данных должна использовать серверную часть, которую вы хотите использовать для первичного тестирования.- База данных с псевдонимом
other
. Базаother
данных используется для проверки того, что запросы могут быть направлены в разные базы данных. Эта база данных должна использовать тот же серверdefault
, что и база данных , и иметь другое имя.
Если вы используете бэкэнд, который не является SQLite, вам нужно будет предоставить другие сведения для каждой базы данных:
- Параметр
USER
должен указать существующую учетную запись пользователя для базы данных. Этому пользователю необходимо разрешение на выполнение, чтобы можно было создать тестовую базу данных.CREATE DATABASE
- Параметр
PASSWORD
должен предоставить пароль дляUSER
указанного.
Тестовые базы данных получают свои имена, добавляя их test_
к значению
NAME
настроек для баз данных, определенных в DATABASES
. Эти тестовые базы данных удаляются по завершении тестов.
Вам также необходимо убедиться, что ваша база данных использует UTF-8 в качестве набора символов по умолчанию. Если ваш сервер базы данных не использует UTF-8 в качестве кодировки по умолчанию, вам нужно будет включить значение для CHARSET
в словарь настроек теста для соответствующей базы данных.
Выполняется только часть тестов ¶
Для запуска всего набора тестов Django требуется время, и запуск каждого отдельного теста может быть избыточным, если, скажем, вы просто добавили тест в Django, который вы хотите запустить быстро, не выполняя все остальное. Вы можете запустить подмножество модульных тестов, добавив имена тестовых модулей runtests.py
в командную строку.
Например, если вы хотите запустить тесты только для общих отношений и интернационализации, введите:
$ ./runtests.py --settings=path.to.settings generic_relations i18n
...\> runtests.py --settings=path.to.settings generic_relations i18n
Как узнать названия отдельных тестов? Загляните внутрь tests/
- в каждом имени каталога есть название теста.
Если вы хотите запустить только определенный класс тестов, вы можете указать список путей к отдельным тестовым классам. Например, для запуска TranslationTests
из i18n
модуля, типа:
$ ./runtests.py --settings=path.to.settings i18n.tests.TranslationTests
...\> runtests.py --settings=path.to.settings i18n.tests.TranslationTests
Помимо этого, вы можете указать индивидуальный метод тестирования следующим образом:
$ ./runtests.py --settings=path.to.settings i18n.tests.TranslationTests.test_lazy_objects
...\> runtests.py --settings=path.to.settings i18n.tests.TranslationTests.test_lazy_objects
Вы можете запускать тесты, начиная с указанного модуля верхнего уровня с помощью --start-at
option. Например:
$ ./runtests.py --start-at=wsgi
...\> runtests.py --start-at=wsgi
Вы также можете запускать тесты, начиная с указанного модуля верхнего уровня с помощью
--start-after
option. Например:
$ ./runtests.py --start-after=wsgi
...\> runtests.py --start-after=wsgi
Обратите внимание, что этот --reverse
параметр не влияет на параметры --start-at
или
--start-after
. Более того, эти параметры нельзя использовать с тестовыми этикетками.
Запуск тестов Selenium ¶
Для некоторых тестов требуется Selenium и веб-браузер. Чтобы запустить эти тесты, вы должны установить пакет selenium и запустить тесты с
--selenium=<BROWSERS>
опцией. Например, если у вас установлены Firefox и Google Chrome:
$ ./runtests.py --selenium=firefox,chrome
...\> runtests.py --selenium=firefox,chrome
Список доступных браузеров см. В пакете selenium.webdriver .
При указании --selenium
автоматически --tags=selenium
запускаются только тесты, требующие селен.
Некоторые браузеры (например, Chrome или Firefox) поддерживают автономное тестирование, которое может быть быстрее и стабильнее. Добавьте --headless
возможность включить этот режим.
Запуск всех тестов ¶
Если вы хотите запустить полный набор тестов, вам необходимо установить ряд зависимостей:
- аргон2- cffi 19.1.0+
- asgiref 3.3.2+ (обязательно)
- bcrypt
- колорама
- Docutils
- geoip2
- jinja2 2.7+
- тупой
- Подушка 6.2.0+
- PyYAML
- pytz (обязательно)
- наблюдатель
- setuptools
- memcached , плюс поддерживаемая привязка Python
- gettext ( gettext в Windows )
- селен
- sqlparse 0.2.2+ (обязательно)
- tblib 1.5.0+
Вы можете найти эти зависимости в файлах требований pip внутри
tests/requirements
каталога исходного дерева Django и установить их следующим образом:
$ python -m pip install -r tests/requirements/py3.txt
...\> py -m pip install -r tests\requirements\py3.txt
Если вы столкнулись с ошибкой во время установки, возможно, в вашей системе отсутствует зависимость для одного или нескольких пакетов Python. Проконсультируйтесь с документацией по неудачному пакету или поищите в Интернете обнаруженное сообщение об ошибке.
Кроме того, можно установить адаптер базы данных (ы) по вашему выбору , используя
oracle.txt
, mysql.txt
или postgres.txt
.
Если вы хотите протестировать бэкэнд кеширования memcached, вам также необходимо определить CACHES
параметр, указывающий на ваш экземпляр memcached.
Чтобы запустить тесты GeoDjango, вам необходимо настроить пространственную базу данных и установить библиотеки геопространственных данных .
Каждая из этих зависимостей не является обязательной. Если вы пропустите какой-либо из них, соответствующие тесты будут пропущены.
Чтобы запустить некоторые тесты автоматической перезагрузки, вам необходимо установить службу Watchman .
Покрытие кода ¶
Участникам предлагается выполнить покрытие набора тестов, чтобы определить области, требующие дополнительных тестов. Установка и использование инструмента покрытия описывается в разделе «Тестирование покрытия кода» .
Чтобы получить точную статистику, покрытие должно выполняться в рамках единого процесса. Чтобы запустить покрытие в тестовом наборе Django с использованием стандартных настроек тестирования:
$ coverage run ./runtests.py --settings=test_sqlite --parallel=1
...\> coverage run runtests.py --settings=test_sqlite --parallel=1
После запуска покрытия сгенерируйте отчет в формате html, запустив:
$ coverage html
...\> coverage html
При выполнении покрытия для тестов Django включенный .coveragerc
файл настроек определяет coverage_html
как выходной каталог для отчета, а также исключает несколько каталогов, не имеющих отношения к результатам (тестовый код или внешний код, включенный в Django).
Приложения Contrib ¶
Тесты для приложений contrib можно найти в tests/
каталоге, обычно в <app_name>_tests
. Например, тесты для contrib.auth
расположены tests/auth_tests
.
Устранение неполадок ¶
Набор тестов зависает или показывает сбои в main
ветке ¶
Убедитесь, что у вас есть последний выпуск поддерживаемой версии Python , поскольку в более ранних версиях часто встречаются ошибки, которые могут привести к сбою или зависанию набора тестов.
В macOS (High Sierra и более новые версии) вы можете увидеть это сообщение в журнале, после чего тесты зависают:
objc[42074]: +[__NSPlaceholderDate initialize] may have been in progress in
another thread when fork() was called.
Чтобы избежать этого, установите OBJC_DISABLE_INITIALIZE_FORK_SAFETY
переменную среды, например:
$ OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES ./runtests.py
Или добавьте в файл запуска вашей оболочки (например ).export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
~/.profile
Множество неудачных тестов с UnicodeEncodeError
¶
Если locales
пакет не установлен, некоторые тесты завершатся ошибкой с расширением
UnicodeEncodeError
.
Вы можете решить эту проблему в системах на основе Debian, например, запустив:
$ apt-get install locales
$ dpkg-reconfigure locales
Вы можете решить эту проблему для систем macOS, настроив локаль своей оболочки:
$ export LANG="en_US.UTF-8"
$ export LC_ALL="en_US.UTF-8"
Запустите locale
команду, чтобы подтвердить изменение. При желании добавьте эти команды экспорта в файл запуска вашей оболочки (например, ~/.bashrc
для Bash), чтобы не вводить их повторно.
Тесты, которые терпят неудачу только в сочетании ¶
В случае, если тест проходит изолированно, но не проходит в рамках всего набора, у нас есть несколько инструментов, которые помогут проанализировать проблему.
--bisect
Вариант runtests.py
будет работать тест неисправного , а вдвое сократить набор тестов он запускается вместе с на каждой итерации, часто делает возможным идентифицировать небольшое количество тестов , которые могут быть связаны с провалом.
Например, предположим, что неудачный тест, который работает сам по себе
ModelTest.test_eq
, затем использует:
$ ./runtests.py --bisect basic.tests.ModelTest.test_eq
...\> runtests.py --bisect basic.tests.ModelTest.test_eq
попытается определить тест, который мешает данному. Сначала тест запускается с первой половиной набора тестов. Если происходит сбой, первая половина набора тестов разделяется на две группы, и каждая группа затем запускается с указанным тестом. Если в первой половине набора тестов нет сбоев, вторая половина набора тестов запускается с указанным тестом и разделяется соответствующим образом, как описано ранее. Процесс повторяется до тех пор, пока набор неудачных тестов не будет сведен к минимуму.
Эта --pair
опция запускает данный тест вместе с каждым другим тестом из набора, позволяя вам проверить, есть ли у другого теста побочные эффекты, вызывающие сбой. Так:
$ ./runtests.py --pair basic.tests.ModelTest.test_eq
...\> runtests.py --pair basic.tests.ModelTest.test_eq
будет сопрягаться test_eq
с каждой тестовой меткой.
С обоими --bisect
и --pair
, если вы уже подозреваете, какие случаи могут быть причиной сбоя, вы можете ограничить перекрестный анализ тестов, указав дополнительные метки тестов после первого:
$ ./runtests.py --pair basic.tests.ModelTest.test_eq queries transactions
...\> runtests.py --pair basic.tests.ModelTest.test_eq queries transactions
Вы также можете попробовать запустить любой набор тестов в обратном порядке, используя эту --reverse
опцию, чтобы убедиться, что выполнение тестов в другом порядке не вызывает никаких проблем:
$ ./runtests.py basic --reverse
...\> runtests.py basic --reverse
Наблюдение за выполнением SQL-запросов во время теста ¶
Если вы хотите проверить выполняемый SQL в неудачных тестах, вы можете включить
ведение журнала SQL, используя --debug-sql
опцию. Если вы объедините это с --verbosity=2
, все запросы SQL будут выведены:
$ ./runtests.py basic --debug-sql
...\> runtests.py basic --debug-sql
Просмотр полного отслеживания неудачного теста ¶
По умолчанию тесты выполняются параллельно, по одному процессу на ядро. Однако, когда тесты выполняются параллельно, вы увидите только усеченную трассировку для любых сбоев теста. Вы можете настроить это поведение с помощью --parallel
опции:
$ ./runtests.py basic --parallel=1
...\> runtests.py basic --parallel=1
Вы также можете использовать DJANGO_TEST_PROCESSES
переменная окружения для этой цели.
Советы по написанию тестов ¶
Регистрация изолирующей модели ¶
Чтобы избежать загрязнения глобального apps
реестра и предотвращения ненужного создания таблиц, модели, определенные в методе тестирования, должны быть привязаны к временному Apps
экземпляру:
from django.apps.registry import Apps
from django.db import models
from django.test import SimpleTestCase
class TestModelDefinition(SimpleTestCase):
def test_model_definition(self):
test_apps = Apps(['app_label'])
class TestModel(models.Model):
class Meta:
apps = test_apps
...
-
django.test.utils.
isolate_apps
( * app_labels , attr_name = None , kwarg_name = None ) ¶
Поскольку этот шаблон включает в себя множество шаблонов, Django предоставляет
isolate_apps()
декоратор. Он используется так:
from django.db import models
from django.test import SimpleTestCase
from django.test.utils import isolate_apps
class TestModelDefinition(SimpleTestCase):
@isolate_apps('app_label')
def test_model_definition(self):
class TestModel(models.Model):
pass
...
Параметр app_label
Моделям, определенным в методе тестирования без явного указания
app_label
, автоматически назначается метка приложения, в котором находится их тестовый класс.
Чтобы убедиться, что модели, определенные в контексте
isolate_apps()
экземпляров, правильно установлены, вы должны передать набор целевых в app_label
качестве аргументов:
from django.db import models
from django.test import SimpleTestCase
from django.test.utils import isolate_apps
class TestModelDefinition(SimpleTestCase):
@isolate_apps('app_label', 'other_app_label')
def test_model_definition(self):
# This model automatically receives app_label='app_label'
class TestModel(models.Model):
pass
class OtherAppModel(models.Model):
class Meta:
app_label = 'other_app_label'
...
Декоратор также может применяться к классам:
from django.db import models
from django.test import SimpleTestCase
from django.test.utils import isolate_apps
@isolate_apps('app_label')
class TestModelDefinition(SimpleTestCase):
def test_model_definition(self):
class TestModel(models.Model):
pass
...
Временный Apps
экземпляр, используемый для изоляции регистрации модели, может быть получен как атрибут при использовании в качестве декоратора класса с помощью
attr_name
параметра:
from django.db import models
from django.test import SimpleTestCase
from django.test.utils import isolate_apps
@isolate_apps('app_label', attr_name='apps')
class TestModelDefinition(SimpleTestCase):
def test_model_definition(self):
class TestModel(models.Model):
pass
self.assertIs(self.apps.get_model('app_label', 'TestModel'), TestModel)
Или в качестве аргумента тестового метода при использовании в качестве декоратора метода с помощью kwarg_name
параметра:
from django.db import models
from django.test import SimpleTestCase
from django.test.utils import isolate_apps
class TestModelDefinition(SimpleTestCase):
@isolate_apps('app_label', kwarg_name='apps')
def test_model_definition(self, apps):
class TestModel(models.Model):
pass
self.assertIs(apps.get_model('app_label', 'TestModel'), TestModel)