django/django
Test framework
django/test/ is Django's testing toolkit: TestCase subclasses, the Client HTTP simulator, the DiscoverRunner test orchestrator, and a pile of helpers that make Django apps testable without spinning up a server.
Purpose
Make it possible to test views, models, forms, templates, and management commands inside a single process, with fast database isolation and accurate URL routing. The framework's own test suite is the most demanding consumer: 1,986 test files, ~348k lines, run on every PR across multiple databases and Python versions.
Directory layout
django/test/
├── __init__.py
├── client.py # Client, AsyncClient, RequestFactory (~58 KB)
├── html.py # parse_html, assertHTMLEqual helpers
├── runner.py # DiscoverRunner, ParallelTestSuite (~37 KB)
├── selenium.py # SeleniumTestCase
├── signals.py # template_rendered, setting_changed
├── testcases.py # SimpleTestCase, TransactionTestCase, TestCase, LiveServerTestCase (~58 KB)
└── utils.py # override_settings, modify_settings, captured_stdout, …Key abstractions
| Type | File | Role |
|---|---|---|
SimpleTestCase |
testcases.py |
No DB; fastest. Inherits unittest.TestCase plus Django assertions |
TransactionTestCase |
testcases.py |
Each test wraps in a transaction-truncate cycle |
TestCase |
testcases.py |
Each test wraps in a transaction that rolls back; the default |
LiveServerTestCase |
testcases.py |
Spins up a thread-served WSGI server |
StaticLiveServerTestCase |
testcases.py |
LiveServerTestCase with staticfiles serving |
Client |
client.py |
Fake HTTP client; bypasses the network |
AsyncClient |
client.py |
Async variant |
RequestFactory |
client.py |
Build HttpRequest instances directly |
DiscoverRunner |
runner.py |
The default test runner |
ParallelTestSuite |
runner.py |
Worker process orchestration |
override_settings, modify_settings |
utils.py |
Decorators / context managers for setting overrides |
CaptureQueriesContext |
utils.py |
Capture every SQL statement in a block |
isolate_apps |
utils.py |
Register temporary apps for a test |
tag |
testcases.py |
@tag decorator for selective runs |
Testing levels
graph TD
Sim["SimpleTestCase<br/>no DB"]
Tx["TestCase<br/>(transaction rollback)"]
Trunc["TransactionTestCase<br/>(truncate)"]
Live["LiveServerTestCase<br/>(thread server)"]
Sel["SeleniumTestCase<br/>(LiveServer + browser)"]
Slow["slowest"]
Fast["fastest"]
Fast --> Sim
Sim --> Tx
Tx --> Trunc
Trunc --> Live
Live --> Sel
Sel --> SlowUse the lightest class that supports your test:
SimpleTestCasefor tests that don't touch the database.TestCasefor the typical case: transactions are rolled back per test, isolation is cheap.TransactionTestCasewhen you need raw SQL, on-commit hooks, or savepoint semantics that the rolled-back outer transaction would interfere with.LiveServerTestCasefor end-to-end tests that need a real socket.
How TestCase isolates state
TestCase.setUpClass() opens a transaction. TestCase.setUp() opens a savepoint. After each test, the savepoint rolls back. After the class finishes, the outer transaction rolls back. The database is never actually mutated.
This is fast (~microseconds per rollback) but means tests can't observe each other's changes. If you need to test transaction commit behaviour, use TransactionTestCase instead.
TestCase.setUpTestData(cls) is a class-method hook for objects that should be created once and shared across all test methods in a class. Each test gets a fresh transaction, but setUpTestData runs in the outer transaction. Use it instead of fixtures for performance.
The test client
django.test.client.Client is a fake HTTP client. It bypasses the network entirely and dispatches requests directly to the WSGI handler:
def test_login(self):
response = self.client.post("/login/", {"username": "alice", "password": "x"})
self.assertRedirects(response, "/")The client maintains state across calls (cookies, session, login). Client.login() sets up an authenticated session without going through the auth views. Client.force_login() bypasses authentication entirely (useful for testing protected views).
AsyncClient mirrors the API for async views. RequestFactory (and AsyncRequestFactory) build HttpRequest instances directly without dispatching — useful for unit-testing view callables.
The client follows redirects by default (configurable). It exposes the rendered template list (response.templates) for assertTemplateUsed. It captures the test database state, the rendered response, and the resolver match.
Assertions
SimpleTestCase adds Django-aware assertions on top of unittest.TestCase:
assertContains(response, text, count=None, status_code=200)assertNotContains(response, text)assertRedirects(response, expected_url, status_code=302, target_status_code=200)assertTemplateUsed(response, template_name)/assertTemplateNotUsedassertFormError(response, form, field, errors)/assertFormSetErrorassertHTMLEqual(html1, html2)/assertHTMLNotEqualassertJSONEqual(json1, json2)/assertJSONNotEqualassertXMLEqual(xml1, xml2)assertNumQueries(num)assertQuerySetEqual(qs, values, transform=None, ordered=True)assertInHTML(needle, haystack)— substring match in normalised HTML.assertRaisesMessage(exception_class, message)—assertRaiseswith substring match onstr(exception).
The runner
DiscoverRunner (django/test/runner.py) does:
- Setup — collect tests via
unittest.defaultTestLoader.discoverfrom each test app. - Database setup —
setup_databases()creates a test DB per configured backend (namedtest_<dbname>). - Run — execute the test suite; in parallel mode, fork workers and dispatch sub-suites.
- Teardown — drop test DBs (unless
--keepdb).
Flags worth knowing:
--keepdb— don't drop the test database between runs. Hugely faster during development.--parallel <N>— fork N worker processes.--reverse— run tests in reverse order. Useful for catching test-ordering bugs.--shuffle [seed]— randomise test order.--debug-sql— print SQL on test failure.--debug-mode— setDEBUG = Trueduring the run.-v 2— verbose output.--tag a --tag b --exclude-tag c— filter by@tagdecorations.--pdb— drop into pdb on error.-k pattern— substring match on test name.
The custom TEST_RUNNER setting lets projects swap in alternatives (pytest-django uses this).
Override settings
override_settings is the workhorse for changing settings inside a test:
@override_settings(DEBUG=True)
def test_with_debug(self):
...
with override_settings(DEBUG=True):
...
@override_settings(DEBUG=True)
class MyTests(TestCase):
...It sends setting_changed so subsystems can rebuild caches. modify_settings is the variant for list-valued settings (MIDDLEWARE, INSTALLED_APPS):
@modify_settings(INSTALLED_APPS={"append": "myapp"})
def test_with_app(self):
...Capturing SQL
from django.test.utils import CaptureQueriesContext
from django.db import connection
with CaptureQueriesContext(connection) as ctx:
...
print(len(ctx.captured_queries))assertNumQueries(n) is the same thing wrapped in an assertion.
Parallelisation
DiscoverRunner forks worker processes (one per --parallel <N>) using multiprocessing. Each worker:
- Gets a copy of the test database (with a unique suffix).
- Runs a partition of the test suite.
- Reports results to the parent.
Tests opt out by setting _overridden_settings["allow_database_queries"] = False (rare) or by being subclasses that don't support parallelisation (TransactionTestCase with serialized_rollback, LiveServerTestCase).
Selenium
django/test/selenium.py provides SeleniumTestCase for browser automation. It's a LiveServerTestCase plus a selenium.webdriver instance. The framework uses it for admin tests that need real browser behaviour.
Integration points
- Settings —
override_settingsinteracts withsetting_changed. - ORM —
setup_databases()andteardown_databases()use the schema editor. - Signals —
template_renderedis fired during template renders soassertTemplateUsedcan collect them. - URL resolver —
Client.get()uses the same resolver as production. - Async support —
AsyncClientandIsolatedAsyncioTestCaseboth work. - Management commands —
runtests.pyandmanage.py testboth delegate here.
Entry points for modification
- Custom test runner: subclass
DiscoverRunner, setTEST_RUNNER. Overriderun_tests,setup_databases,teardown_databases. - New assertion: add a method to
SimpleTestCaseif it's broadly useful, otherwise extend in a project base class. - New
TestCasemix-in: subclassSimpleTestCaseorTestCaseand add the helpers.
Key source files
| File | Purpose |
|---|---|
django/test/testcases.py |
All *TestCase classes (~58 KB) |
django/test/client.py |
Client, AsyncClient, RequestFactory (~58 KB) |
django/test/runner.py |
DiscoverRunner, parallel suite (~37 KB) |
django/test/utils.py |
override_settings, CaptureQueriesContext, helpers |
django/test/selenium.py |
SeleniumTestCase |
django/test/signals.py |
template_rendered, setting_changed |
django/test/html.py |
parse_html and assertHTMLEqual machinery |
Where to read tests
tests/test_runner/— the runner itself.tests/test_client/,tests/test_client_regress/—Clientbehaviour.tests/test_utils/— utilities likeoverride_settings.tests/transaction_hooks/—on_commitand transaction interaction.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.