pytest-django
pytest-django is an active plugin for the pytest testing framework that enables efficient testing of Django projects and applications. It integrates pytest's powerful fixture system, reduced boilerplate, and advanced test capabilities with Django's ORM and components. The library maintains a regular release cadence, with multiple minor versions and occasional major updates throughout the year, ensuring compatibility with the latest Django and Python versions.
Warnings
- breaking Major versions of pytest-django often drop support for older, unsupported Python, Django, and pytest versions. Ensure your environment meets the minimum requirements for the pytest-django version you are installing.
- gotcha By default, Django's `DEBUG` setting is set to `False` during test runs, regardless of its value in your settings file. This aligns with Django's default test runner behavior to simulate a production environment.
- gotcha Tests that attempt to access the database without explicit permission will fail. `pytest-django` requires you to explicitly mark tests or request fixtures that need database access.
- gotcha Incorrectly configuring `DJANGO_SETTINGS_MODULE` can lead to import errors (`"could not import myproject.settings"`) or tests running without the proper Django environment.
- gotcha Using the `--reuse-db` option significantly speeds up test runs by keeping the database between sessions. However, it will not automatically pick up schema changes. If models are altered, the database schema will be out of sync.
- gotcha Directly importing your Django project's `settings.py` module (e.g., `from myproject import settings`) in test files can cause issues with `pytest-django`'s setting overrides or when settings are dynamically configured.
Install
-
pip install pytest-django
Imports
- pytest.mark.django_db
import pytest @pytest.mark.django_db def test_my_database_function(): ... - settings (fixture)
def test_with_custom_setting(settings): settings.DEBUG = True assert settings.DEBUG is True - client (fixture)
def test_my_view(client): response = client.get('/my-url/') assert response.status_code == 200 - admin_client (fixture)
def test_admin_view(admin_client): response = admin_client.get('/admin/') assert response.status_code == 200
Quickstart
# myproject/pytest.ini
[pytest]
DJANGO_SETTINGS_MODULE = myproject.settings
python_files = tests.py test_*.py *_tests.py
addopts = --reuse-db
# myproject/myproject/settings.py (abbreviated)
# ... standard Django settings ...
INSTALLED_APPS = [
# ...
'myapp',
# ...
]
# myproject/myapp/models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
def __str__(self):
return self.title
# myproject/myapp/tests.py
import pytest
from myapp.models import Book
@pytest.mark.django_db
def test_book_creation():
# The 'db' fixture or 'pytest.mark.django_db' is required for database access.
book = Book.objects.create(title='The Great Adventure', author='Jane Doe')
assert Book.objects.count() == 1
assert book.title == 'The Great Adventure'