Django Test Runner
The first thing to do is install django-nose using pip: Then make these additions to your project’s settings.py: Here, we’re setting a couple of command-line arguments to be included every time we run python manage.py test. The -with-coverage option says we want a coverage report, and the -cover-package option lists all of the modules we. Django-nose provides all the goodness of nose in your Django tests, like: Running the tests in one or more specific modules (or apps, or classes, or folders, or just running a specific test) Obviating the need to import all your tests into tests/init.py. This not only saves busy-work but also eliminates the possibility of accidentally.
See also
The testing tutorial, the testing toolsreference, and the advanced testing topics.
This document is split into two primary sections. First, we explain how to writetests with Django. Then, we explain how to run them.
Writing tests¶
Django’s unit tests use a Python standard library module: unittest
. Thismodule defines tests using a class-based approach.
Here is an example which subclasses from django.test.TestCase
,which is a subclass of unittest.TestCase
that runs each test inside atransaction to provide isolation:
When you run your tests, the default behavior of thetest utility is to find all the test cases (that is, subclasses ofunittest.TestCase
) in any file whose name begins with test
,automatically build a test suite out of those test cases, and run that suite.
For more details about unittest
, see the Python documentation.
Where should the tests live?
The default startapp
template creates a tests.py
file in thenew application. This might be fine if you only have a few tests, but asyour test suite grows you’ll likely want to restructure it into a testspackage so you can split your tests into different submodules such astest_models.py
, test_views.py
, test_forms.py
, etc. Feel free topick whatever organizational scheme you like.
See also Using the Django test runner to test reusable applications.
Warning
If your tests rely on database access such as creating or querying models,be sure to create your test classes as subclasses ofdjango.test.TestCase
rather than unittest.TestCase
.
Using unittest.TestCase
avoids the cost of running each test in atransaction and flushing the database, but if your tests interact withthe database their behavior will vary based on the order that the testrunner executes them. This can lead to unit tests that pass when run inisolation but fail when run in a suite.
Running tests¶
Once you’ve written tests, run them using the test
command ofyour project’s manage.py
utility:
Test discovery is based on the unittest module’s built-in testdiscovery. By default, this will discover tests inany file named “test*.py” under the current working directory.
You can specify particular tests to run by supplying any number of “testlabels” to ./manage.pytest
. Each test label can be a full Python dottedpath to a package, module, TestCase
subclass, or test method. For instance:
You can also provide a path to a directory to discover tests below thatdirectory:
You can specify a custom filename pattern match using the -p
(or--pattern
) option, if your test files are named differently from thetest*.py
pattern:
If you press Ctrl-C
while the tests are running, the test runner willwait for the currently running test to complete and then exit gracefully.During a graceful exit the test runner will output details of any testfailures, report on how many tests were run and how many errors and failureswere encountered, and destroy any test databases as usual. Thus pressingCtrl-C
can be very useful if you forget to pass the --failfast
option, notice that some tests are unexpectedly failing andwant to get details on the failures without waiting for the full test run tocomplete.
If you do not want to wait for the currently running test to finish, youcan press Ctrl-C
a second time and the test run will halt immediately,but not gracefully. No details of the tests run before the interruption willbe reported, and any test databases created by the run will not be destroyed.
Test with warnings enabled
It’s a good idea to run your tests with Python warnings enabled:python-Wamanage.pytest
. The -Wa
flag tells Python todisplay deprecation warnings. Django, like many other Python libraries,uses these warnings to flag when features are going away. It also mightflag areas in your code that aren’t strictly wrong but could benefitfrom a better implementation.
The test database¶
Tests that require a database (namely, model tests) will not use your “real”(production) database. Separate, blank databases are created for the tests.
Regardless of whether the tests pass or fail, the test databases are destroyedwhen all the tests have been executed.
You can prevent the test databases from being destroyed by using thetest--keepdb
option. This will preserve the test database betweenruns. If the database does not exist, it will first be created. Any migrationswill also be applied in order to keep it up to date.
As described in the previous section, if a test run is forcefully interrupted,the test database may not be destroyed. On the next run, you’ll be askedwhether you want to reuse or destroy the database. Use the test--noinput
option to suppress that prompt and automatically destroy thedatabase. This can be useful when running tests on a continuous integrationserver where tests may be interrupted by a timeout, for example.
The default test database names are created by prepending test_
to thevalue of each NAME
in DATABASES
. When using SQLite, thetests will use an in-memory database by default (i.e., the database will becreated in memory, bypassing the filesystem entirely!). The TEST
dictionary in DATABASES
offers a number of settingsto configure your test database. For example, if you want to use a differentdatabase name, specify NAME
in the TEST
dictionary for any given database in DATABASES
.
On PostgreSQL, USER
will also need read access to the built-inpostgres
database.
Aside from using a separate database, the test runner will otherwiseuse all of the same database settings you have in your settings file:ENGINE
, USER
, HOST
, etc. Thetest database is created by the user specified by USER
, so you’llneed to make sure that the given user account has sufficient privileges tocreate a new database on the system.
For fine-grained control over the character encoding of your testdatabase, use the CHARSET
TEST option. If you’re usingMySQL, you can also use the COLLATION
option tocontrol the particular collation used by the test database. See thesettings documentation for details of theseand other advanced settings.
If using an SQLite in-memory database with SQLite, shared cache is enabled, so you can write testswith ability to share the database between threads.
Finding data from your production database when running tests?
If your code attempts to access the database when its modules are compiled,this will occur before the test database is set up, with potentiallyunexpected results. For example, if you have a database query inmodule-level code and a real database exists, production data could polluteyour tests. It is a bad idea to have such import-time database queries inyour code anyway - rewrite your code so that it doesn’t do this.
This also applies to customized implementations ofready()
.
Order in which tests are executed¶
In order to guarantee that all TestCase
code starts with a clean database,the Django test runner reorders tests in the following way:
- All
TestCase
subclasses are run first. - Then, all other Django-based tests (test cases based on
SimpleTestCase
, includingTransactionTestCase
) are run with no particularordering guaranteed nor enforced among them. - Then any other
unittest.TestCase
tests (including doctests) that mayalter the database without restoring it to its original state are run.
Note
The new ordering of tests may reveal unexpected dependencies on test caseordering. This is the case with doctests that relied on state left in thedatabase by a given TransactionTestCase
test, theymust be updated to be able to run independently.
You may reverse the execution order inside groups using the test--reverse
option. This can help with ensuring your tests are independent fromeach other.
Rollback emulation¶
Any initial data loaded in migrations will only be available in TestCase
tests and not in TransactionTestCase
tests, and additionally only onbackends where transactions are supported (the most important exception beingMyISAM). This is also true for tests which rely on TransactionTestCase
such as LiveServerTestCase
andStaticLiveServerTestCase
.
Django can reload that data for you on a per-testcase basis bysetting the serialized_rollback
option to True
in the body of theTestCase
or TransactionTestCase
, but note that this will slow downthat test suite by approximately 3x.
Third-party apps or those developing against MyISAM will need to set this;in general, however, you should be developing your own projects against atransactional database and be using TestCase
for most tests, and thusnot need this setting.
The initial serialization is usually very quick, but if you wish to excludesome apps from this process (and speed up test runs slightly), you may addthose apps to TEST_NON_SERIALIZED_APPS
.
To prevent serialized data from being loaded twice, settingserialized_rollback=True
disables thepost_migrate
signal when flushing the testdatabase.
Other test conditions¶
Regardless of the value of the DEBUG
setting in your configurationfile, all Django tests run with DEBUG
=False. This is to ensure thatthe observed output of your code matches what will be seen in a productionsetting.
Caches are not cleared after each test, and running “manage.py test fooapp” caninsert data from the tests into the cache of a live system if you run yourtests in production because, unlike databases, a separate “test cache” is notused. This behavior may change in the future.
Understanding the test output¶
When you run your tests, you’ll see a number of messages as the test runnerprepares itself. You can control the level of detail of these messages with theverbosity
option on the command line:
This tells you that the test runner is creating a test database, as describedin the previous section.
Once the test database has been created, Django will run your tests.If everything goes well, you’ll see something like this:
If there are test failures, however, you’ll see full details about which testsfailed:
A full explanation of this error output is beyond the scope of this document,but it’s pretty intuitive. You can consult the documentation of Python’sunittest
library for details.
Note that the return code for the test-runner script is 1 for any number offailed and erroneous tests. If all the tests pass, the return code is 0. Thisfeature is useful if you’re using the test-runner script in a shell script andneed to test for success or failure at that level.
Speeding up the tests¶
Running tests in parallel¶
As long as your tests are properly isolated, you can run them in parallel togain a speed up on multi-core hardware. See test--parallel
.
Password hashing¶
The default password hasher is rather slow by design. If you’re authenticatingmany users in your tests, you may want to use a custom settings file and setthe PASSWORD_HASHERS
setting to a faster hashing algorithm:
Don’t forget to also include in PASSWORD_HASHERS
any hashingalgorithm used in fixtures, if any.
Preserving the test database¶
The test--keepdb
option preserves the test database between testruns. It skips the create and destroy actions which can greatly decrease thetime to run tests.
Released:
django test runner to use py.test tests
Project description
This project allows you to use py.test as a django test runner, instead of thedefault test runner.
To use it, add it to your python path and add django_pytest to your installedapps. Also set the TEST_RUNNER = ‘django_pytest.test_runner.run_tests’ setting.If you’re using Django 1.3 or newer setTEST_RUNNER = ‘django_pytest.test_runner.TestRunner’ or Django will printdeprecation warnings each time you run your tests.
Also create a conftest.py in your project directory and include:
from django_pytest.conftest import pytest_funcarg__client, pytest_funcarg__django_client
You can also use:
from django_pytest.auth_funcargs import pytest_funcarg__user, pytest_funcarg__groups
to import a user or some groups with users in them
Now anywhere in your project, you can create files calledtest_<something>.py. These are standard py.test test files. Use the funcargclient in every test to both instantiate a test database that is clearedafter each test and to provide you with a django test client object identicalto the one used in django’s test system. For example:
def test_filter(client):response = client.get(‘/browse/’, {‘filter’: ‘1’})assert response.status_code 200
Use ./manage.py test to run the py.test test runs (ie: it replaces thestandard django test runner). You can pass py.test options to the commandand they will be forwarded to py.test. (Technically, I haven’t got it passingall options, just the most common ones I use)
The management command has been set up so that syncdb will use the django coresyncdb if SOUTH_TESTS_MIGRATE is set to False, if south is installed. Thisprevents migrations from running when running unit tests. This speeds up testsetup significantly, but it means your test db may not be identical toproduction, if you have faulty migrations.
py.test automatically picks up any subclasses of unittest.TestCase, providedthey are in a module named test_<something>.py. Thus, all your existing djangounittests should work seemlessly with py.test, although you may have to renameyour test files if they do not conform to this convention. You can also writecustom py.test test collection hooks to pick up test modules that are named ina different directory structure.
Django Test Suite Runner
This project differs from <http://github.com/bfirsh/pytest_django> in that itprovides a django test runner that calls py.test, rather than creating apy.test plugin to test django projects. I believe there is overlappingfunctionality from the two projects, and also that they can be integrated intoa single project, but I have not looked at the feasibility of this yet.
Release historyRelease notifications | RSS feed
0.2.0
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Filename, size | File type | Python version | Upload date | Hashes |
---|---|---|---|---|
Filename, size django-pytest-0.2.0.tar.gz (5.9 kB) | File type Source | Python version None | Upload date | Hashes |
Hashes for django-pytest-0.2.0.tar.gz
Django Test Runner Pytest
Algorithm | Hash digest |
---|---|
SHA256 | de21f20f9e7eb941529d75078b18192506a9f6d4ae80f86fbe2f3bcac8e09d71 |
MD5 | f44f8792994501c37efaf7d44b7baf4e |
BLAKE2-256 | b2e22a87105042c08a6f116aac1d9c666e89982a4f707652a0f7d76e8a88b554 |