Passed Run of Oct 18, 16:20
pytest --flakytest-profile --flakytest-rate 1000.
Where the time goes
Test time by category- Database12.24 s
- Libraries7.72 s
- Migrations3.38 s
- Password hashing2.42 s
- DB schema2.41 s
- Imports1.19 s
- Templates633 ms
- App code560 ms
- Serialization342 ms
- Unsampled312 ms
- Deep copies160 ms
- pytest152 ms
- Factories63 ms
- Test code18 ms
Session timeline
Fix next
Ranked by the time each fix saves per runRun 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
Make the test database server skip durability work
Tests spend 18.0s (57%) in the database. Test databases don't need to survive a crash, so the server can skip flushing to disk.
Details
Only affects crash safety of the throwaway test server; query behaviour is identical.
Where:
- apps/projects/models.py:466 save · 416 ms
- apps/projects/profiles.py:313 write_snapshots · 320 ms
- apps/api/tests.py:73 setUp · 238 ms
- apps/projects/profiles.py:458 write_perfs · 227 ms
- apps/api/tests.py:76 join_workers · 226 ms
- apps/projects/rollups.py:88 add_perfs · 194 ms
- apps/projects/profiles.py:479 finalize_profile · 190 ms
- apps/projects/models.py:230 upsert · 188 ms
- apps/projects/environments.py:63 get_or_create_environment · 183 ms
- apps/projects/tests.py:953 setUp · 167 ms
Most affected tests:
- apps/api/tests.py::TestApiIndex::test_index
- apps/projects/tests.py::SeedDemoCommandTest::test_seed_demo
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_end_after_progress
- apps/api/tests.py::ProfileUploadQueueTest::test_upload_is_processed_by_the_worker
- apps/projects/tests.py::ProfilePagePaginationTest::test_slowest_tests_first_then_the_next_page
- apps/api/tests.py::IngestStartEndpointTest::test_results_are_counted_and_the_payload_dropped
- apps/api/tests.py::IngestStartEndpointTest::test_all_test_status_types
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_start_progress_end
Stop re-running migrations on every test run
Migrations take 3.4s per run, before the first test can start.
Details
CI should still build the database from scratch (no --reuse-db) so broken migrations are caught.
Most affected tests:
- apps/api/tests.py::TestApiIndex::test_index
Use a fast password hasher in tests
2.4s (8% of test time) is spent hashing passwords. Slow hashing protects real passwords; in tests it only burns CPU.
Details
Only change the hasher in test settings. Tests that assert on a specific hash format need updating.
Where:
- ft/tests.py:205 test_change_password · 552 ms
- apps/orgs/tests.py:30 test_signing_up_creates_an_organization · 304 ms
- ft/tests.py:161 test_signup · 288 ms
- apps/orgs/tests.py:194 test_superusers_can_open_any_project_but_dont_list_them · 281 ms
- ft/tests.py:200 test_change_password · 267 ms
- ft/tests.py:230 test_projects_only_lists_your_own_even_for_superusers · 259 ms
- ft/tests.py:175 setUpTestData · 231 ms
- ft/tests.py:213 test_change_password · 226 ms
- apps/projects/tests.py:1353 setUpTestData · 6 ms
Most affected tests:
- ft/tests.py::TestAccountSettings::test_change_password
- apps/orgs/tests.py::SignupTest::test_signing_up_creates_an_organization
- ft/tests.py::TestAccountPages::test_signup
- apps/orgs/tests.py::SuperuserTest::test_superusers_can_open_any_project_but_dont_list_them
- ft/tests.py::TestAccountSettings::test_projects_only_lists_your_own_even_for_superusers
- apps/projects/tests.py::MemoryTest::test_dashboard_shows_the_tests_with_most_memory
Use TestCase instead of TransactionTestCase
1.6s goes to flushing every table after tests in 11 TransactionTestCase / transaction=True / live_server tests.
Details
Tests that rely on commit behaviour, multiple connections or a live server still need a transactional test case.
Most affected tests:
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_end_after_progress
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_multiple_sessions
- apps/api/tests.py::ProfileUploadQueueTest::test_upload_is_processed_by_the_worker
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_start_progress_end
- apps/api/tests.py::IngestStartEndpointTest::test_details_are_kept_for_failures_only
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_valid
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_progress_before_start
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_start_with_git
Tests open new database connections over and over
Connecting to the database takes 1.3s.
Details
Where:
- apps/api/tests.py:76 join_workers · 191 ms
- apps/api/tests.py:73 setUp · 171 ms
- apps/api/tests.py:928 setUp · 84 ms
- apps/api/tasks.py:266 warm_reports · 81 ms
- apps/api/urls.py:72 wrapped_view · 48 ms
- apps/api/tests.py:306 test_details_are_kept_for_failures_only · 20 ms
- apps/api/tests.py:212 test_ingest_start_progress_end · 17 ms
- apps/api/tasks.py:237 process_profile · 17 ms
- apps/api/tests.py:988 test_upload_is_processed_by_the_worker · 17 ms
- apps/api/tests.py:331 test_results_are_counted_and_the_payload_dropped · 13 ms
Most affected tests:
- apps/api/tests.py::IngestStartEndpointTest::test_results_are_counted_and_the_payload_dropped
- apps/api/tests.py::IngestStartEndpointTest::test_all_test_status_types
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_progress_before_start
- apps/api/tests.py::ProfileUploadLockTest::test_upload_while_a_part_is_being_processed
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_start_progress_end
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_end_after_progress
- apps/api/tests.py::ProfileUploadQueueTest::test_upload_is_processed_by_the_worker
- apps/api/tests.py::IngestStartEndpointTest::test_details_are_kept_for_failures_only
Create shared test data in setUpTestData instead of setUp
setUp() runs before every test and takes 941ms in total (db 887ms, library 40ms, factories 6ms) in 13 classes: SettingsTest (3 tests), ProjectsPageTest (5 tests), ProjectEditPage (6 tests), ProjectDeletePage (4 tests).
Details
Since Django 3.2 attributes assigned in setUpTestData are deep-copied per test, so in-memory changes don't leak between tests. Keep objects a test modifies in the database (or re-fetches) as before.
Where:
- apps/api/tests.py:73 setUp · 244 ms
- apps/projects/tests.py:953 setUp · 180 ms
- apps/api/tests.py:928 setUp · 105 ms
- apps/projects/tests.py:337 setUp · 75 ms
- apps/projects/tests.py:142 setUp · 56 ms
- apps/projects/tests.py:412 setUp · 50 ms
- apps/projects/tests.py:218 setUp · 49 ms
- apps/projects/tests.py:1375 setUp · 43 ms
- apps/projects/tests.py:187 setUp · 29 ms
- apps/projects/tests.py:307 setUp · 26 ms
Most affected tests:
- apps/api/tests.py::ProfileUploadLockTest::test_upload_while_a_part_is_being_processed
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_start_with_git
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_progress_before_start
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_multiple_sessions
- apps/api/tests.py::IngestStartEndpointTest::test_details_are_kept_for_failures_only
- apps/api/tests.py::IngestStartEndpointTest::test_all_test_status_types
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_end_after_progress
- apps/projects/tests.py::ProjectTestsPage::test_project_with_no_tests
Modules are imported while tests run
1.2s of test time is spent importing modules: whichever test imports a heavy module first pays for it, which makes that test look slow (and varies with test order).
Details
Where:
- ft/urls.py:35 <module> · 379 ms
- apps/api/tests.py:42 test_index · 126 ms
- ft/urls.py:152 <module> · 99 ms
- apps/projects/urls.py:501 project_profile · 51 ms
- apps/projects/urls.py:8 <module> · 16 ms
- apps/projects/tests.py:1143 test_seed_demo · 13 ms
- apps/api/tests.py:76 join_workers · 11 ms
- apps/projects/migrations/0011_environments_profiles.py:182 Migration · 8 ms
- ft/urls.py:181 <module> · 7 ms
- ft/urls.py:151 <module> · 7 ms
Most affected tests:
- apps/api/tests.py::TestApiIndex::test_index
- apps/api/tests.py::ProfileUploadTest::test_missing_parts_mark_the_profile_incomplete
- apps/projects/tests.py::SeedDemoCommandTest::test_seed_demo
- apps/api/tests.py::IngestStartEndpointTest::test_ingest_multiple_sessions
- apps/orgs/tests.py::MembersTest::test_owner_invites_someone_who_signs_up
- apps/api/tests.py::IngestStartEndpointTest::test_all_test_status_types
- apps/projects/tests.py::IndexPageTest::test_index_page
- apps/projects/tests.py::MemoryTest::test_memory_tests_are_ranked_by_average_peak
Tests
1–200 of 235, slowest first · click a column to sort this pageMemory
The test process peaked at 199 MBSlowest fixtures
Exact setup time across the session| Fixture | Scope | Calls | Total |
|---|---|---|---|
| _django_setup_unittest | class | 50 | 4.57 s |
| django_db_setup | session | 1 | 4.54 s |
| _unittest_setUpClass_fixture_ProjectPagesTest | class | 1 | 312 ms |
| _unittest_setUpClass_fixture_ProfilePagePaginationTest | class | 1 | 272 ms |
| _unittest_setUpClass_fixture_TestAccountSettings | class | 1 | 238 ms |
| _unittest_setUpClass_fixture_McpTest | class | 1 | 216 ms |
| _unittest_setUpClass_fixture_AnalyticsTest | class | 1 | 195 ms |
| _unittest_setUpClass_fixture_RealProfileDocumentTest | class | 1 | 159 ms |
| _unittest_setUpClass_fixture_MemoryTest | class | 1 | 95 ms |
| _unittest_setUpClass_fixture_StorageTest | class | 1 | 95 ms |
| _unittest_setUpClass_fixture_FlakyReportTest | class | 1 | 78 ms |
| _unittest_setUpClass_fixture_LegacyUrlTest | class | 1 | 68 ms |
| _unittest_setUpClass_fixture_FlakyReportCacheTest | class | 1 | 65 ms |
| _unittest_setUpClass_fixture_ProjectRunsPage | class | 1 | 33 ms |
| _unittest_setUpClass_fixture_SlugTest | class | 1 | 29 ms |