==========Unit tests==========Django comes with a test suite of its own, in the ``tests`` directory of thecode base. It's our policy to make sure all tests pass at all times.We appreciate any and all contributions to the test suite!The Django tests all use the testing infrastructure that ships with Django fortesting applications. See :doc:`/topics/testing/overview` for an explanation ofhow to write new tests... _running-unit-tests:Running the unit tests======================Quickstart----------First, `fork Django on GitHub <https://github.com/django/django/fork>`__.Second, create and activate a virtual environment. If you're not familiar withhow to do that, read our :doc:`contributing tutorial </intro/contributing>`.Next, clone your fork, install some requirements, and run the tests:.. console::$ 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.pyInstalling the requirements will likely require some operating system packagesthat your computer doesn't have installed. You can usually figure out whichpackage to install by doing a web search for the last line or so of the errormessage. Try adding your operating system to the search query if needed.If you have trouble installing the requirements, you can skip that step. See:ref:`running-unit-tests-dependencies` for details on installing the optionaltest dependencies. If you don't have an optional dependency installed, thetests that require it will be skipped.Running the tests requires a Django settings module that defines the databasesto use. To help you get started, Django provides and uses a sample settingsmodule that uses the SQLite database. See :ref:`running-unit-tests-settings` tolearn how to use a different settings module to run the tests with a differentdatabase.Having problems? See :ref:`troubleshooting-unit-tests` for some common issues.Running tests using ``tox``---------------------------`Tox <https://tox.wiki/>`_ is a tool for running tests in different virtualenvironments. Django includes a basic ``tox.ini`` that automates some checksthat our build server performs on pull requests. To run the unit tests andother checks (such as :ref:`import sorting <coding-style-imports>`, the:ref:`documentation spelling checker <documentation-spelling-check>`, and:ref:`code formatting <coding-style-python>`), install and run the ``tox``command from any place in the Django source tree:.. console::$ python -m pip install tox$ toxBy default, ``tox`` runs the test suite with the bundled test settings file forSQLite, ``black``, ``flake8``, ``isort``, and the documentation spellingchecker. In addition to the system dependencies noted elsewhere in thisdocumentation, the command ``python3`` must be on your path and linked to theappropriate version of Python. A list of default environments can be seen asfollows:.. console::$ tox -lpy3blackflake8>=3.7.0docsisort>=5.1.0Testing other Python versions and database backends~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~In addition to the default environments, ``tox`` supports running unit testsfor other versions of Python and other database backends. Since Django's testsuite doesn't bundle a settings file for database backends other than SQLite,however, you must :ref:`create and provide your own test settings<running-unit-tests-settings>`. For example, to run the tests on Python 3.9using PostgreSQL:.. console::$ tox -e py39-postgres -- --settings=my_postgres_settingsThis command sets up a Python 3.9 virtual environment, installs Django'stest suite dependencies (including those for PostgreSQL), and calls``runtests.py`` with the supplied arguments (in this case,``--settings=my_postgres_settings``).The remainder of this documentation shows commands for running tests without``tox``, however, any option passed to ``runtests.py`` can also be passed to``tox`` by prefixing the argument list with ``--``, as above.``Tox`` also respects the :envvar:`DJANGO_SETTINGS_MODULE` environmentvariable, if set. For example, the following is equivalent to the commandabove:.. code-block:: console$ DJANGO_SETTINGS_MODULE=my_postgres_settings tox -e py39-postgresWindows users should use:.. code-block:: doscon...\> set DJANGO_SETTINGS_MODULE=my_postgres_settings...\> tox -e py39-postgresRunning the JavaScript tests~~~~~~~~~~~~~~~~~~~~~~~~~~~~Django includes a set of :ref:`JavaScript unit tests <javascript-tests>` forfunctions in certain contrib apps. The JavaScript tests aren't run by defaultusing ``tox`` because they require ``Node.js`` to be installed and aren'tnecessary for the majority of patches. To run the JavaScript tests using``tox``:.. console::$ tox -e javascriptThis command runs ``npm install`` to ensure test requirements are up todate and then runs ``npm test``.Running tests using ``django-docker-box``-----------------------------------------`django-docker-box`_ allows you to run the Django's test suite across allsupported databases and python versions. See the `django-docker-box`_ projectpage for installation and usage instructions... _django-docker-box: https://github.com/django/django-docker-box/.. _running-unit-tests-settings:Using another ``settings`` module---------------------------------The included settings module (``tests/test_sqlite.py``) allows you to run thetest suite using SQLite. If you want to run the tests using a differentdatabase, you'll need to define your own settings file. Some tests, such asthose for ``contrib.postgres``, are specific to a particular database backendand will be skipped if run with a different backend. Some tests are skipped orexpected failures on a particular database backend (see``DatabaseFeatures.django_test_skips`` and``DatabaseFeatures.django_test_expected_failures`` on each backend).To run the tests with different settings, ensure that the module is on your:envvar:`PYTHONPATH` and pass the module with ``--settings``.The :setting:`DATABASES` setting in any test settings module needs to definetwo databases:* A ``default`` database. This database should use the backend thatyou want to use for primary testing.* A database with the alias ``other``. The ``other`` database is used to testthat queries can be directed to different databases. This database should usethe same backend as the ``default``, and it must have a different name.If you're using a backend that isn't SQLite, you will need to provide otherdetails for each database:* The :setting:`USER` option needs to specify an existing user accountfor the database. That user needs permission to execute ``CREATE DATABASE``so that the test database can be created.* The :setting:`PASSWORD` option needs to provide the password forthe :setting:`USER` that has been specified.Test databases get their names by prepending ``test_`` to the value of the:setting:`NAME` settings for the databases defined in :setting:`DATABASES`.These test databases are deleted when the tests are finished.You will also need to ensure that your database uses UTF-8 as the defaultcharacter set. If your database server doesn't use UTF-8 as a default charset,you will need to include a value for :setting:`CHARSET <TEST_CHARSET>` in thetest settings dictionary for the applicable database... _runtests-specifying-labels:Running only some of the tests------------------------------Django's entire test suite takes a while to run, and running every single testcould be redundant if, say, you just added a test to Django that you want torun quickly without running everything else. You can run a subset of the unittests by appending the names of the test modules to ``runtests.py`` on thecommand line.For example, if you'd like to run tests only for generic relations andinternationalization, type:.. console::$ ./runtests.py --settings=path.to.settings generic_relations i18nHow do you find out the names of individual tests? Look in ``tests/`` — eachdirectory name there is the name of a test.If you want to run only a particular class of tests, you can specify a list ofpaths to individual test classes. For example, to run the ``TranslationTests``of the ``i18n`` module, type:.. console::$ ./runtests.py --settings=path.to.settings i18n.tests.TranslationTestsGoing beyond that, you can specify an individual test method like this:.. console::$ ./runtests.py --settings=path.to.settings i18n.tests.TranslationTests.test_lazy_objectsYou can run tests starting at a specified top-level module with ``--start-at``option. For example:.. console::$ ./runtests.py --start-at=wsgiYou can also run tests starting after a specified top-level module with``--start-after`` option. For example:.. console::$ ./runtests.py --start-after=wsgiNote that the ``--reverse`` option doesn't impact on ``--start-at`` or``--start-after`` options. Moreover these options cannot be used with testlabels.Running the Selenium tests--------------------------Some tests require Selenium and a web browser. To run these tests, you mustinstall the selenium_ package and run the tests with the``--selenium=<BROWSERS>`` option. For example, if you have Firefox and GoogleChrome installed:.. console::$ ./runtests.py --selenium=firefox,chromeSee the `selenium.webdriver`_ package for the list of available browsers.Specifying ``--selenium`` automatically sets ``--tags=selenium`` to run onlythe tests that require selenium.Some browsers (e.g. Chrome or Firefox) support headless testing, which can befaster and more stable. Add the ``--headless`` option to enable this mode... _selenium.webdriver: https://github.com/SeleniumHQ/selenium/tree/trunk/py/selenium/webdriver.. _running-unit-tests-dependencies:Running all the tests---------------------If you want to run the full suite of tests, you'll need to install a number ofdependencies:* aiosmtpd_* argon2-cffi_ 19.1.0+* asgiref_ 3.5.2+ (required)* bcrypt_* colorama_* docutils_* geoip2_* jinja2_ 2.7+* numpy_* Pillow_ 6.2.0+* PyYAML_* pytz_ (required)* pywatchman_* redis_* setuptools_* memcached_, plus a :ref:`supported Python binding <memcached>`* gettext_ (:ref:`gettext_on_windows`)* selenium_* sqlparse_ 0.2.2+ (required)* tblib_ 1.5.0+You can find these dependencies in `pip requirements files`_ inside the``tests/requirements`` directory of the Django source tree and install themlike so:.. console::$ python -m pip install -r tests/requirements/py3.txtIf you encounter an error during the installation, your system might be missinga dependency for one or more of the Python packages. Consult the failingpackage's documentation or search the web with the error message that youencounter.You can also install the database adapter(s) of your choice using``oracle.txt``, ``mysql.txt``, or ``postgres.txt``.If you want to test the memcached or Redis cache backends, you'll also need todefine a :setting:`CACHES` setting that points at your memcached or Redisinstance respectively.To run the GeoDjango tests, you will need to :doc:`set up a spatial databaseand install the Geospatial libraries</ref/contrib/gis/install/index>`.Each of these dependencies is optional. If you're missing any of them, theassociated tests will be skipped.To run some of the autoreload tests, you'll need to install the Watchman_service... _aiosmtpd: https://pypi.org/project/aiosmtpd/.. _argon2-cffi: https://pypi.org/project/argon2-cffi/.. _asgiref: https://pypi.org/project/asgiref/.. _bcrypt: https://pypi.org/project/bcrypt/.. _colorama: https://pypi.org/project/colorama/.. _docutils: https://pypi.org/project/docutils/.. _geoip2: https://pypi.org/project/geoip2/.. _jinja2: https://pypi.org/project/Jinja2/.. _numpy: https://pypi.org/project/numpy/.. _Pillow: https://pypi.org/project/Pillow/.. _PyYAML: https://pyyaml.org/wiki/PyYAML.. _pytz: https://pypi.org/project/pytz/.. _pywatchman: https://pypi.org/project/pywatchman/.. _redis: https://pypi.org/project/redis/.. _setuptools: https://pypi.org/project/setuptools/.. _memcached: https://memcached.org/.. _gettext: https://www.gnu.org/software/gettext/manual/gettext.html.. _selenium: https://pypi.org/project/selenium/.. _sqlparse: https://pypi.org/project/sqlparse/.. _pip requirements files: https://pip.pypa.io/en/latest/user_guide/#requirements-files.. _tblib: https://pypi.org/project/tblib/.. _Watchman: https://facebook.github.io/watchman/Code coverage-------------Contributors are encouraged to run coverage on the test suite to identify areasthat need additional tests. The coverage tool installation and use is describedin :ref:`testing code coverage<topics-testing-code-coverage>`.Coverage should be run in a single process to obtain accurate statistics. Torun coverage on the Django test suite using the standard test settings:.. console::$ coverage run ./runtests.py --settings=test_sqlite --parallel=1After running coverage, generate the html report by running:.. console::$ coverage htmlWhen running coverage for the Django tests, the included ``.coveragerc``settings file defines ``coverage_html`` as the output directory for the reportand also excludes several directories not relevant to the results(test code or external code included in Django)... _contrib-apps:Contrib apps============Tests for contrib apps can be found in the ``tests/`` directory, typicallyunder ``<app_name>_tests``. For example, tests for ``contrib.auth`` are locatedin ``tests/auth_tests``... _troubleshooting-unit-tests:Troubleshooting===============Test suite hangs or shows failures on ``main`` branch-----------------------------------------------------Ensure you have the latest point release of a :ref:`supported Python version<faq-python-version-support>`, since there are often bugs in earlier versionsthat may cause the test suite to fail or hang.On **macOS** (High Sierra and newer versions), you might see this messagelogged, after which the tests hang::objc[42074]: +[__NSPlaceholderDate initialize] may have been in progress inanother thread when fork() was called.To avoid this set a ``OBJC_DISABLE_INITIALIZE_FORK_SAFETY`` environmentvariable, for example::$ OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES ./runtests.pyOr add ``export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES`` to your shell'sstartup file (e.g. ``~/.profile``).Many test failures with ``UnicodeEncodeError``----------------------------------------------If the ``locales`` package is not installed, some tests will fail with a``UnicodeEncodeError``.You can resolve this on Debian-based systems, for example, by running:.. code-block:: console$ apt-get install locales$ dpkg-reconfigure localesYou can resolve this for macOS systems by configuring your shell's locale:.. code-block:: console$ export LANG="en_US.UTF-8"$ export LC_ALL="en_US.UTF-8"Run the ``locale`` command to confirm the change. Optionally, add those exportcommands to your shell's startup file (e.g. ``~/.bashrc`` for Bash) to avoidhaving to retype them.Tests that only fail in combination-----------------------------------In case a test passes when run in isolation but fails within the whole suite,we have some tools to help analyze the problem.The ``--bisect`` option of ``runtests.py`` will run the failing test whilehalving the test set it is run together with on each iteration, often makingit possible to identify a small number of tests that may be related to thefailure.For example, suppose that the failing test that works on its own is``ModelTest.test_eq``, then using:.. console::$ ./runtests.py --bisect basic.tests.ModelTest.test_eqwill try to determine a test that interferes with the given one. First, thetest is run with the first half of the test suite. If a failure occurs, thefirst half of the test suite is split in two groups and each group is then runwith the specified test. If there is no failure with the first half of the testsuite, the second half of the test suite is run with the specified test andsplit appropriately as described earlier. The process repeats until the set offailing tests is minimized.The ``--pair`` option runs the given test alongside every other test from thesuite, letting you check if another test has side-effects that cause thefailure. So:.. console::$ ./runtests.py --pair basic.tests.ModelTest.test_eqwill pair ``test_eq`` with every test label.With both ``--bisect`` and ``--pair``, if you already suspect which casesmight be responsible for the failure, you may limit tests to be cross-analyzedby :ref:`specifying further test labels <runtests-specifying-labels>` afterthe first one:.. console::$ ./runtests.py --pair basic.tests.ModelTest.test_eq queries transactionsYou can also try running any set of tests in a random or reverse order usingthe ``--shuffle`` and ``--reverse`` options. This can help verify thatexecuting tests in a different order does not cause any trouble:.. console::$ ./runtests.py basic --shuffle$ ./runtests.py basic --reverseSeeing the SQL queries run during a test----------------------------------------If you wish to examine the SQL being run in failing tests, you can turn on:ref:`SQL logging <django-db-logger>` using the ``--debug-sql`` option. If youcombine this with ``--verbosity=2``, all SQL queries will be output:.. console::$ ./runtests.py basic --debug-sqlSeeing the full traceback of a test failure-------------------------------------------By default tests are run in parallel with one process per core. When the testsare run in parallel, however, you'll only see a truncated traceback for anytest failures. You can adjust this behavior with the ``--parallel`` option:.. console::$ ./runtests.py basic --parallel=1You can also use the :envvar:`DJANGO_TEST_PROCESSES` environment variable forthis purpose.Tips for writing tests======================.. highlight:: pythonIsolating model registration----------------------------To avoid polluting the global :attr:`~django.apps.apps` registry and preventunnecessary table creation, models defined in a test method should be bound toa temporary ``Apps`` instance. To do this, use the:func:`~django.test.utils.isolate_apps` decorator::from django.db import modelsfrom django.test import SimpleTestCasefrom django.test.utils import isolate_appsclass TestModelDefinition(SimpleTestCase):@isolate_apps('app_label')def test_model_definition(self):class TestModel(models.Model):pass..... admonition:: Setting ``app_label``Models defined in a test method with no explicit:attr:`~django.db.models.Options.app_label` are automatically assigned thelabel of the app in which their test class is located.In order to make sure the models defined within the context of:func:`~django.test.utils.isolate_apps` instances are correctlyinstalled, you should pass the set of targeted ``app_label`` as arguments:.. code-block:: python:caption: ``tests/app_label/tests.py``from django.db import modelsfrom django.test import SimpleTestCasefrom django.test.utils import isolate_appsclass 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):passclass OtherAppModel(models.Model):class Meta:app_label = 'other_app_label'...