Django Test Performance
Use this as the orchestration skill for speeding up a Django test suite. Do not start by changing settings blindly; first measure the suite and then pick the smallest safe optimization with a repeatable verification command.
Core Workflow
Establish a baseline.
- Run the same command developers or CI use.
- Capture wall-clock time, runner, settings module, database backend, worker count, and branch.
- If the cause is unclear, use
django-test-profilingbefore changing behavior.
Classify the dominant cost.
- Startup/import/discovery: reduce collection scope and expensive app initialization.
- Database creation/migrations: reuse DB locally, squash migration history, or improve database storage.
- Per-test setup: reduce fixture data, use factories, and use
setUpTestData. - External backends: replace file storage, cache, task queues, and instrumentation with test-safe backends.
- Long tail of tests: parallelize after isolation checks.
Apply low-risk wins first.
- Fast password hasher.
DEBUG = Falsein tests.- Disable database serialization when serialized rollback is not needed.
- Disable debug toolbar, Sentry/Rollbar/APM initialization, and other instrumentation.
- In-memory or local test backends for storage, cache, and task queues.
- See speed-wins.md.
Improve data and structure.
- Use
django-test-datafor factory, fixture,setUpTestData,TestCase, and integration-vs-unit decisions.
- Use
Improve migrations and database setup.
- Use
--keepdbor--reuse-dbfor local repeat runs. - Force rebuilds when migration history changes.
- Prefer squashing migrations over disabling migrations globally.
- Keep the test database backend close to production unless the project is database-agnostic.
- Use
Parallelize only when safe.
- Use
django-test-parallelizationfor order isolation, shared resources, and worker configuration.
- Use
Re-measure with the original baseline command.
- Report before/after runtime and the changed risk surface.
- Keep or revert each optimization based on measured impact and behavioral fidelity.
Default Commands
time python manage.py test
python manage.py test --timing
python manage.py test --keepdb
time pytest
pytest --durations 20
pytest --reuse-db
pytest --create-db
Decision Rules
- If you cannot name the bottleneck, profile first.
- If a setting changes production-like behavior, keep the override narrow and document why tests remain representative.
- Avoid broad
TESTING = Truebranches in application code; use explicit settings and test helpers. - Do not swap PostgreSQL/MySQL/MariaDB projects to SQLite just for speed unless production is SQLite or the project intentionally supports many backends.
- Do not disable migrations as the normal path. If a legacy project insists, run real migrations in CI.
- Keep local speed shortcuts from hiding CI coverage. CI should run slow tests and migration-realistic paths somewhere.
Handoff Map
| Situation | Use |
|---|---|
| Need timings, slow-test lists, flame graphs, or cProfile output | django-test-profiling |
Enabling --parallel, pytest-xdist, or debugging random failures |
django-test-parallelization |
Fixture bloat, factories, setUpTestData, TestCase class choices |
django-test-data |
| Mocking settings, HTTP, time, output, or command input safely | django-targeted-mocking |
| CI cache, split jobs, slow markers, runner scale | django-ci-test-optimization |
Verification
Before finishing, provide:
- Baseline and final runtime from the same command.
- A ranked list of changes made or recommended.
- Risks introduced by each test-only override.
- Commands the project should keep for local and CI verification.
Source: hashgraph-online/awesome-codex-plugins → plugins/LVTD-LLC/skills/skills/django-test-performance/SKILL.md