Django Test Profiling
Use this skill before changing a Django test suite for speed. Measurement decides which optimization is worth doing; otherwise it is easy to spend time on harmless settings while the real cost sits in startup, database setup, fixture construction, or a small set of slow tests.
Measurement Workflow
Capture a full wall-clock baseline.
- Prefer shell timing because it includes Python startup, Django import time, test discovery, database setup, and teardown.
- Record the exact command, environment, and repeat count.
Separate framework phases when possible.
- For Django's runner, use
--timing to see database setup and teardown.
- For pytest, compare shell timing with
pytest --durations.
Find the slowest tests.
- For pytest-django, start with
pytest --durations 20.
- For Django's runner, use an existing slow-test plugin or a small custom runner only when the project does not already have one.
Profile only after you know where the time goes.
- Use
py-spy first for a low-overhead whole-run view.
- Use
cProfile when you need exhaustive Python call data.
Convert the result into a ranked action list.
- Identify whether the expensive part is startup, database creation, repeated setup, test data, query count, I/O, cache/file/storage access, or a specific test body.
- Hand off to
django-test-performance, django-test-data, or django-test-parallelization when the next step fits those skills.
Commands
time python manage.py test
python manage.py test --timing
pytest --durations 20
For profiling command variants and interpretation guidance, read profiler-commands.md.
Decision Rules
- Treat shell timing as the authoritative user-visible duration.
- Use Django
--timing when database setup or teardown may dominate.
- Optimize the slowest measured tests first, not the tests that look suspicious.
- Put noisy duration reports in CI logs when they distract from normal local runs.
- Use
py-spy --subprocesses when the test runner uses child processes.
- Sort cProfile by cumulative time first; inspect self-time only after you understand the caller chain.
Common Mistakes
- Trusting a framework's final "ran in X seconds" line as the complete runtime.
- Comparing Django runner timing and pytest timing as if they measure identical phases.
- Profiling everything before finding slow tests.
- Reading unsorted cProfile output and chasing import internals.
- Expecting sampling profiles to catch every short hot path.
- Optimizing a helper without checking how often it is reached by tests.
Verification
Before reporting findings, include:
- The exact baseline command and measured wall-clock time.
- The slowest tests or slowest phases.
- The profiler used, if any, and why it was appropriate.
- The top 3 practical next actions, ordered by expected impact.
Source: hashgraph-online/awesome-codex-plugins → plugins/LVTD-LLC/skills/skills/django-test-profiling/SKILL.md
1---2name: django-test-profiling3description: Profile and measure slow Django test suites with Django's runner, pytest-django, shell timing, py-spy, cProfile, pytest durations, and profiler visualizations. Use when a Django project has slow tests, unclear test-runtime bottlenecks, CI timing problems, startup overhead, database setup overhead, or a request to find the slowest tests before optimizing.4---567# Django Test Profiling89Use this skill before changing a Django test suite for speed. Measurement decides which optimization is worth doing; otherwise it is easy to spend time on harmless settings while the real cost sits in startup, database setup, fixture construction, or a small set of slow tests.1011## Measurement Workflow12131. Capture a full wall-clock baseline.14 - Prefer shell timing because it includes Python startup, Django import time, test discovery, database setup, and teardown.15 - Record the exact command, environment, and repeat count.16172. Separate framework phases when possible.18 - For Django's runner, use `--timing` to see database setup and teardown.19 - For pytest, compare shell timing with `pytest --durations`.20213. Find the slowest tests.22 - For pytest-django, start with `pytest --durations 20`.23 - For Django's runner, use an existing slow-test plugin or a small custom runner only when the project does not already have one.24254. Profile only after you know where the time goes.26 - Use `py-spy` first for a low-overhead whole-run view.27 - Use `cProfile` when you need exhaustive Python call data.28295. Convert the result into a ranked action list.30 - Identify whether the expensive part is startup, database creation, repeated setup, test data, query count, I/O, cache/file/storage access, or a specific test body.31 - Hand off to `django-test-performance`, `django-test-data`, or `django-test-parallelization` when the next step fits those skills.3233## Commands3435```bash36time python manage.py test37python manage.py test --timing38pytest --durations 2039```4041For profiling command variants and interpretation guidance, read [profiler-commands.md](references/profiler-commands.md).4243## Decision Rules4445- Treat shell timing as the authoritative user-visible duration.46- Use Django `--timing` when database setup or teardown may dominate.47- Optimize the slowest measured tests first, not the tests that look suspicious.48- Put noisy duration reports in CI logs when they distract from normal local runs.49- Use `py-spy --subprocesses` when the test runner uses child processes.50- Sort cProfile by cumulative time first; inspect self-time only after you understand the caller chain.5152## Common Mistakes5354- Trusting a framework's final "ran in X seconds" line as the complete runtime.55- Comparing Django runner timing and pytest timing as if they measure identical phases.56- Profiling everything before finding slow tests.57- Reading unsorted cProfile output and chasing import internals.58- Expecting sampling profiles to catch every short hot path.59- Optimizing a helper without checking how often it is reached by tests.6061## Verification6263Before reporting findings, include:6465- The exact baseline command and measured wall-clock time.66- The slowest tests or slowest phases.67- The profiler used, if any, and why it was appropriate.68- The top 3 practical next actions, ordered by expected impact.6970---7172**Source:** [`hashgraph-online/awesome-codex-plugins`](https://github.com/hashgraph-online/awesome-codex-plugins) → `plugins/LVTD-LLC/skills/skills/django-test-profiling/SKILL.md`