Test suite performance
Suite wall time per run
Click a point to open the runWhere the time goes
Avg test time per runSlowest tests
All tests →Most memory
All tests by memory →Fix next
From the latest run per environment, by time savedRun tests in parallel on all 2 CPUs
Tests run one at a time: 31.6s of test time on a 2-CPU machine. With pytest-xdist this could take about 15.8s.
Details
Tests must not share state: files in fixed paths, ports, a shared database without per-worker names, or module globals. Run with -p randomly first to shake out order dependencies.
Use plain static file storage in tests
Static file storage/manifest handling costs 13.3s.
Details
Where:
- apps/api/tests.py:487 upload · 820 ms
- apps/mcp/tests.py:66 post · 681 ms
- ft/tests.py:205 test_change_password · 560 ms
- apps/orgs/tests.py:30 test_signing_up_creates_an_organization · 390 ms
- ft/urls.py:35 <module> · 379 ms
- apps/api/tests.py:352 ingest_start · 363 ms
- ft/tests.py:161 test_signup · 293 ms
- apps/projects/urls.py:501 project_profile · 289 ms
- ft/tests.py:200 test_change_password · 269 ms
- apps/api/tests.py:98 ingest_start · 211 ms
Most affected tests:
- ft/tests.py::TestAccountSettings::test_change_password
- apps/api/tests.py::TestApiIndex::test_index
- apps/orgs/tests.py::SignupTest::test_signing_up_creates_an_organization
- apps/projects/tests.py::ProjectPagesTest::test_dashboard_filters
- ft/tests.py::TestAccountPages::test_signup
- apps/api/tests.py::ProfileUploadTest::test_missing_parts_mark_the_profile_incomplete
- apps/projects/tests.py::ProjectPagesTest::test_configure_page
- ft/tests.py::TestTrubleshootingPage::test_troubleshooting
Disable django-debug-toolbar in tests
django-debug-toolbar is installed in the test settings and costs 6.6s.
Details
Where:
- ft/tests.py:205 test_change_password · 560 ms
- ft/urls.py:35 <module> · 379 ms
- apps/orgs/tests.py:30 test_signing_up_creates_an_organization · 371 ms
- ft/tests.py:161 test_signup · 293 ms
- apps/projects/urls.py:501 project_profile · 289 ms
- ft/tests.py:200 test_change_password · 269 ms
- apps/api/urls.py:72 wrapped_view · 170 ms
- apps/projects/urls.py:49 find_project · 148 ms
- apps/projects/analytics.py:264 latest_profiles · 104 ms
- ft/urls.py:45 index · 102 ms
Most affected tests:
- ft/tests.py::TestAccountSettings::test_change_password
- apps/api/tests.py::TestApiIndex::test_index
- apps/orgs/tests.py::SignupTest::test_signing_up_creates_an_organization
- ft/tests.py::TestAccountPages::test_signup
- apps/projects/tests.py::ProjectPagesTest::test_dashboard_filters
- apps/api/tests.py::ProfileUploadTest::test_missing_parts_mark_the_profile_incomplete
- apps/api/tests.py::ProfileUploadTest::test_upload_adds_migrations_per_worker_insight
- apps/projects/tests.py::ProjectPagesTest::test_dashboard_public_by_slug
Repeated queries (N+1) in the code under test
27 tests run the same query 10+ times, e.g. 180x in test_seed_demo. N+1 queries slow the tests and production alike.
Details
This changes application code, so it speeds up production too; the tests stay as they are.
- 180x in test_seed_demo: SELECT "projects_test"."id", "projects_test"."name", "projects_test"."project_id", "projects_test"."slug", "projects_test"."date_last_run", "projects_test"."date_first_seen", "projects_test"."first_commit_id", "projects_test"."muted" FROM "projects_test" WHERE ("projects_test"."name" = %s AND "proj…
- 22x in test_dashboard_filters: SELECT "projects_environment"."id", "projects_environment"."project_id", "projects_environment"."name", "projects_environment"."kind", "projects_environment"."provider", "projects_environment"."details", "projects_environment"."date_first_seen", "projects_environment"."date_last_seen" FROM "project…
- 21x in test_configure_page: SELECT "projects_profile"."id", "projects_profile"."project_id", "projects_profile"."number", "projects_profile"."environment_id", "projects_profile"."session_id", "projects_profile"."run_id", "projects_profile"."commit_id", "projects_profile"."ingest_id", "projects_profile"."external_id", "project…
- 20x in test_index: SELECT "django_content_type"."model" AS "model" FROM "django_content_type" WHERE "django_content_type"."app_label" = %s
- 20x in test_daily_stats_count_a_profile_once_every_part_is_in: SELECT "projects_profilepart"."id", "projects_profilepart"."profile_id", "projects_profilepart"."index", "projects_profilepart"."count", "projects_profilepart"."checksum", "projects_profilepart"."status", "projects_profilepart"."error", "projects_profilepart"."tests_count", "projects_profilepart"."…
Most affected tests:
- apps/projects/tests.py::SeedDemoCommandTest::test_seed_demo
- apps/projects/tests.py::ProjectPagesTest::test_dashboard_filters
- apps/projects/tests.py::ProjectPagesTest::test_configure_page
- apps/api/tests.py::TestApiIndex::test_index
- apps/api/tests.py::ProfileUploadTest::test_daily_stats_count_a_profile_once_every_part_is_in
- apps/api/tests.py::IngestStartEndpointTest::test_all_test_status_types
- apps/api/tests.py::IngestStartEndpointTest::test_details_are_kept_for_failures_only
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_end_after_progress
CI vs local
Tests that are much slower in CI, and whyUpload profiles from CI and from a developer machine to compare them.
Locally: FLAKYTEST_SECRET_TOKEN=… pytest --flakytest-profile
Failing and flaky tests
Environments
Every CI job and developer machine that reported in the last 7 days| Environment | Profiled runs | Avg wall time |
|---|---|---|
| CI github-actions:test | 3 | 30.72 s |
| CI github-actions | 0 | – |