Testing Basics¶
pytest-django Quick Start¶
pytest-django is a plugin for pytest that provides a set of useful tools for testing Django applications and projects. For more information see the pytest-django documentation.
To install pytest-django:
$ pip install -U pytest-django
...
The DJANGO_SETTINGS_MODULE environment variable must be defined and should point
to the django settings module used for testing. There are different approaches towards
configuration.
Use
pytest.inito defineDJANGO_SETTINGS_MODULEvariable:# -- FILE: pytest.ini (or tox.ini) [pytest] DJANGO_SETTINGS_MODULE = myapp.tests.settings # -- recommended but optional: python_files = tests.py test_*.py *_tests.py
Set
DJANGO_SETTINGS_MODULEenvironment variable, e.g. in bash or Windows Command prompt$ export DJANGO_SETTINGS_MODULE = myapp.tests.settings $ pytest
Use
pytest_configurehook# -- FILE: conftest.py import os from pathlib import Path import sys import django TESTS_DIR = Path(__file__).resolve().parent BASE_DIR = TESTS_DIR.parent sys.path.insert(0, BASE_DIR.absolute()) def pytest_configure(): os.environ['DJANGO_SETTINGS_MODULE'] = 'myapp.tests.settings' django.setup()
See also pytest_configure hook
Use
--ds=SETTINGcommand line option$ pytest --ds=myapp.tests.settings
Variant to this method is to add the command line option to
pytest.ini:addopts = --ds=myapp.tests.settings
How the setting is choosen? The precedence (from higher to lower) is as follows:
The command line option
--dsThe command line option
--dsfrompytest.iniortox.iniThe environment variable
DJANGO_SETTINGS_MODULEThe
DJANGO_SETTINGS_MODULEoption in the configuration file -pytest.ini(tox.ini)
To override settings you can use the setting fixutre.
@pytest.fixture(autouse=True)
def use_dummy_cache_backend(settings):
settings.CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.dummy.DummyCache",
}
}
settings module for testing¶
import os
# Define environment variables for testing
os.environ['DJANGO_SECRET_KEY'] = 'secret-key'
# Get everything from production settings module
from myproj.settings import *
# Use in-memory database for better testing performance
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
}
}
Testing with database¶
In order for a test to have access to the database it must either be marked using the django_db() mark or request one of the db, transactional_db or django_db_reset_sequences fixtures. Otherwise the test will fail when trying to access the database.
pytest.mark.django_db is used to mark a test function as requiring the database.
It will ensure the database is set up correctly for the test. Each test will run in its own
transaction which will be rolled back at the end of the test. This behavior is the same as
Django’s standard TestCase class.
@pytest.mark.django_db
def test_user_model():
user = User(username='joe')
assert str(user) == user
Testing with client¶
Use client fixture - An instance of a django.test.Client.
def test_with_client(client):
response = client.get('/')
assert response.status_code == 200
For situations where logged in user is required, following are useful:
admin_userfixture - An instance of a superuser, with username “admin” and password “password” (in case there is no “admin” user yet).admin_clientfixture - An instance of a django.test.Client, logged in as an admin user.client.force_log()method
def test_authenticated(client, admin_user):
client.force_login(admin_user)
response = client.get('/admin/')
assert response.status_code == 200
def test_authenticated(admin_client):
response = client.get('/admin/')
assert response.status_code == 200
Further information: