Модульные тесты¶
Django поставляется с собственным набором тестов в каталоге tests
кодовой базы. Наша политика заключается в том, чтобы все тесты всегда проходили.
Мы ценим любой и всякий вклад в тестовый пакет!
Все тесты Django используют инфраструктуру тестирования, поставляемую вместе с Django для тестирования приложений. См. Написание и выполнение тестов для объяснения того, как писать новые тесты.
Запуск модульных тестов¶
Быстрый старт¶
Во-первых, fork Django on GitHub.
Во-вторых, создайте и активируйте виртуальную среду. Если вы не знаете, как это сделать, прочитайте нашу статью contributing tutorial.
Затем клонируйте ваш форк, установите некоторые требования и запустите тесты:
$ 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 requirements\py3.txt
...\> runtests.py
Installing the requirements will likely require some operating system packages that your computer doesn’t have installed. You can usually figure out which package to install by doing a web search for the last line or so of the error message. Try adding your operating system to the search query if needed.
Если у вас возникли проблемы с установкой требований, вы можете пропустить этот шаг. Смотрите Выполнение всех тестов для получения подробной информации об установке необязательных зависимостей тестов. Если у вас не установлена дополнительная зависимость, тесты, требующие ее установки, будут пропущены.
Для запуска тестов требуется модуль настроек Django, определяющий используемые базы данных. Чтобы помочь вам начать, Django предоставляет и использует пример модуля настроек, который использует базу данных SQLite. Смотрите Использование другого модуля settings, чтобы узнать, как использовать другой модуль настроек для запуска тестов с другой базой данных.
Возникли проблемы? Некоторые распространенные проблемы описаны в разделе Устранение неполадок.
Запуск тестов с использованием tox
¶
Tox is a tool for running tests in different virtual
environments. Django includes a basic tox.ini
that automates some checks
that our build server performs on pull requests. To run the unit tests and
other checks (such as import sorting, the
documentation spelling checker, and
code formatting), install and run the tox
command from any place in the Django source tree:
$ python -m pip install tox
$ tox
...\> py -m pip install tox
...\> tox
By default, tox
runs the test suite with the bundled test settings file for
SQLite, black
, flake8
, isort
, and the documentation spelling
checker. In addition to the system dependencies noted elsewhere in this
documentation, the command python3
must be on your path and linked to the
appropriate version of Python. A list of default environments can be seen as
follows:
$ tox -l
py3
black
flake8>=3.7.0
docs
isort>=5.1.0
...\> tox -l
py3
black
flake8>=3.7.0
docs
isort>=5.1.0
Тестирование других версий Python и бэкендов баз данных¶
In addition to the default environments, tox
supports running unit tests
for other versions of Python and other database backends. Since Django’s test
suite doesn’t bundle a settings file for database backends other than SQLite,
however, you must create and provide your own test settings. For example, to run the tests on Python 3.9
using PostgreSQL:
$ tox -e py39-postgres -- --settings=my_postgres_settings
...\> tox -e py39-postgres -- --settings=my_postgres_settings
This command sets up a Python 3.9 virtual environment, installs Django’s
test suite dependencies (including those for PostgreSQL), and calls
runtests.py
with the supplied arguments (in this case,
--settings=my_postgres_settings
).
Остальная часть этой документации показывает команды для запуска тестов без tox
, однако, любой параметр, переданный в runtests.py
, также может быть передан в tox
, префикснув список аргументов с --
, как указано выше.
Tox
also respects the DJANGO_SETTINGS_MODULE
environment
variable, if set. For example, the following is equivalent to the command
above:
$ DJANGO_SETTINGS_MODULE=my_postgres_settings tox -e py39-postgres
Пользователи Windows должны использовать:
...\> set DJANGO_SETTINGS_MODULE=my_postgres_settings
...\> tox -e py39-postgres
Выполнение тестов JavaScript¶
Django включает набор JavaScript unit tests для функций в некоторых приложениях 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
¶
The included settings module (tests/test_sqlite.py
) allows you to run the
test suite using SQLite. If you want to run the tests using a different
database, you’ll need to define your own settings file. Some tests, such as
those for contrib.postgres
, are specific to a particular database backend
and will be skipped if run with a different backend. Some tests are skipped or
expected failures on a particular database backend (see
DatabaseFeatures.django_test_skips
and
DatabaseFeatures.django_test_expected_failures
on each backend).
Чтобы запустить тесты с разными настройками, убедитесь, что модуль находится на вашем 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
. Например:
$ ./runtests.py --start-at=wsgi
...\> runtests.py --start-at=wsgi
Вы также можете запускать тесты, начиная после указанного модуля верхнего уровня с помощью опции --start-after
. Например:
$ ./runtests.py --start-after=wsgi
...\> runtests.py --start-after=wsgi
Обратите внимание, что опция --reverse
не влияет на опции --start-at
или --start-after
. Кроме того, эти опции нельзя использовать с тестовыми метками.
Запуск тестов Selenium¶
Some tests require Selenium and a web browser. To run these tests, you must
install the selenium package and run the tests with the
--selenium=<BROWSERS>
option. For example, if you have Firefox and Google
Chrome installed:
$ ./runtests.py --selenium=firefox,chrome
...\> runtests.py --selenium=firefox,chrome
Список доступных браузеров см. в пакете selenium.webdriver.
Указание --selenium
автоматически устанавливает --tags=selenium
для запуска только тех тестов, для которых требуется selenium.
Некоторые браузеры (например, Chrome или Firefox) поддерживают безголовое тестирование, которое может быть быстрее и стабильнее. Добавьте опцию --headless
, чтобы включить этот режим.
Выполнение всех тестов¶
Если вы хотите запустить полный набор тестов, вам потребуется установить ряд зависимостей:
- aiosmtpd
- argon2-cffi 19.1.0+
- asgiref 3.6.0+ (required)
- bcrypt
- colorama
- docutils
- geoip2
- jinja2 2.7+
- numpy
- Pillow 6.2.0+
- PyYAML
- pytz (обязательно)
- сторож
- redis
- setuptools
- memcached, плюс supported Python binding
- gettext (gettext в Windows)
- селен
- sqlparse 0.2.3+ (required)
- tblib 1.5.0+
Вы можете найти эти зависимости в каталоге pip requirements files внутри каталога tests/requirements
дерева исходников Django и установить их следующим образом:
$ python -m pip install -r tests/requirements/py3.txt
...\> py -m pip install -r tests\requirements\py3.txt
If you encounter an error during the installation, your system might be missing a dependency for one or more of the Python packages. Consult the failing package’s documentation or search the web with the error message that you encounter.
Вы также можете установить адаптер(ы) базы данных по вашему выбору, используя oracle.txt
, mysql.txt
или postgres.txt
.
If you want to test the memcached or Redis cache backends, you’ll also need to
define a CACHES
setting that points at your memcached or Redis
instance respectively.
To run the GeoDjango tests, you will need to set up a spatial database and install the Geospatial libraries.
Каждая из этих зависимостей является необязательной. Если какая-либо из них отсутствует, связанные с ней тесты будут пропущены.
Чтобы запустить некоторые тесты автозагрузки, вам нужно установить службу Watchman.
Покрытие кода¶
Соавторам рекомендуется выполнять покрытие тестового набора для выявления областей, нуждающихся в дополнительных тестах. Установка и использование инструмента покрытия описаны в testing code coverage.
Для получения точной статистики покрытие следует запускать в одном процессе. Чтобы запустить покрытие на тестовом наборе 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-приложения¶
Tests for contrib apps can be found in the tests/ directory, typically
under <app_name>_tests
. For example, tests for contrib.auth
are located
in tests/auth_tests.
Устранение неполадок¶
Test suite hangs or shows failures on main
branch¶
Убедитесь, что у вас есть последний точечный релиз supported Python version, поскольку в более ранних версиях часто встречаются ошибки, которые могут привести к сбою или зависанию набора тестов.
На 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
, если вы уже подозреваете, какие случаи могут быть причиной сбоя, вы можете ограничить тесты для перекрестного анализа с помощью specifying further test labels после первого:
$ ./runtests.py --pair basic.tests.ModelTest.test_eq queries transactions
...\> runtests.py --pair basic.tests.ModelTest.test_eq queries transactions
You can also try running any set of tests in a random or reverse order using
the --shuffle
and --reverse
options. This can help verify that
executing tests in a different order does not cause any trouble:
$ ./runtests.py basic --shuffle
$ ./runtests.py basic --reverse
...\> runtests.py basic --shuffle
...\> runtests.py basic --reverse
Просмотр SQL-запросов, выполняемых во время тестирования¶
Если вы хотите изучить SQL, выполняемый в неудачных тестах, вы можете включить SQL logging, используя опцию --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
.
Советы по написанию тестов¶
Изолирующая регистрация модели¶
To avoid polluting the global apps
registry and prevent
unnecessary table creation, models defined in a test method should be bound to
a temporary Apps
instance. To do this, use the
isolate_apps()
decorator:
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'
...