flakytest.dev anze3db flakytest
Profiles / #1

Passed Run of Oct 18, 15:53

CI github-actions:test · 78a4357 main dirty · pass/fail report
Some tests got too few samples to explain their time. Rerun with pytest --flakytest-profile --flakytest-rate 1000.
Wall time
32.33 s
1 worker
Test time
26.31 s
sum of test durations
Tests
225
225 passed
Profiler
py-spy
500 Hz · 11,074 samples · Python 3.14.8 · flakytest 2026.0b1
Peak memory
169 MB
test process

Where the time goes

Test time by category
  • Database11.55 s
  • Libraries5.51 s
  • Migrations2.84 s
  • Password hashing2.61 s
  • DB schema1.46 s
  • Imports550 ms
  • Templates449 ms
  • App code400 ms
  • Serialization310 ms
  • Unsampled270 ms
  • pytest196 ms
  • Deep copies86 ms
  • Factories31 ms
  • Test code17 ms
  • Logging16 ms
  • Waiting10 ms
  • Mocking9 ms

Session timeline

Other
1.57 s
Tests
23.74 s
Startup
2.11 s
Collection
270 ms
Between tests
3.95 s
Session teardown
532 ms
Test phases
Setup 5.70 s Call 20.47 s Teardown 134 ms

Fix next

Ranked by the time each fix saves per run
1

Run tests in parallel on all 2 CPUs

Tests run one at a time: 26.3s of test time on a 2-CPU machine. With pytest-xdist this could take about 13.2s.

High Parallelism
13.15 s per run
Fix: pip install pytest-xdist, then run pytest -n auto (add it to addopts, or only in CI). pytest-django creates a separate test database per worker automatically.
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.

Documentation

2

Use plain static file storage in tests

Static file storage/manifest handling costs 11.3s.

High App code
11.31 s per run
Fix: In test settings use STORAGES["staticfiles"] = {"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage"} so templates don't need a manifest.
Details

Where:

  • apps/mcp/tests.py:66 post · 712 ms
  • ft/tests.py:205 test_change_password · 599 ms
  • apps/api/tests.py:487 upload · 470 ms
  • apps/orgs/tests.py:30 test_signing_up_creates_an_organization · 382 ms
  • ft/tests.py:200 test_change_password · 328 ms
  • ft/tests.py:161 test_signup · 320 ms
  • apps/projects/urls.py:634 <module> · 231 ms
  • apps/api/urls.py:72 wrapped_view · 216 ms
  • apps/projects/tests.py:146 test_not_logged_in · 202 ms
  • apps/projects/tests.py:973 test_dashboard_public_by_slug · 199 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/projects/tests.py::ProjectPagesTest::test_dashboard_filters
  • apps/api/tests.py::TestApiIndex::test_index
  • apps/projects/tests.py::ProjectPagesTest::test_dashboard_public_by_slug
  • apps/api/tests.py::ProfileUploadTest::test_missing_parts_mark_the_profile_incomplete
  • apps/projects/tests.py::ProjectEditPage::test_not_logged_in
3

Disable django-debug-toolbar in tests

django-debug-toolbar is installed in the test settings and costs 6.7s.

High App code
6.69 s per run
Fix: Only add debug_toolbar to INSTALLED_APPS and MIDDLEWARE when not testing (e.g. `if DEBUG and not TESTING:`).
Details

Where:

  • ft/tests.py:205 test_change_password · 599 ms
  • apps/orgs/tests.py:30 test_signing_up_creates_an_organization · 367 ms
  • ft/tests.py:200 test_change_password · 328 ms
  • ft/tests.py:161 test_signup · 320 ms
  • apps/projects/urls.py:634 <module> · 231 ms
  • apps/api/urls.py:72 wrapped_view · 216 ms
  • apps/projects/urls.py:508 project_profile · 198 ms
  • apps/orgs/views.py:32 org_shell · 184 ms
  • apps/api/urls.py:59 touch_token · 127 ms
  • apps/projects/urls.py:50 find_project · 127 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/projects/tests.py::ProjectPagesTest::test_dashboard_filters
  • apps/api/tests.py::TestApiIndex::test_index
  • apps/api/tests.py::ProfileUploadTest::test_missing_parts_mark_the_profile_incomplete
  • apps/projects/tests.py::ProjectPagesTest::test_dashboard
  • apps/projects/tests.py::ProfilePagePaginationTest::test_slowest_tests_first_then_the_next_page

Documentation

4

Repeated queries (N+1) in the code under test

25 tests run the same query 10+ times, e.g. 180x in test_seed_demo. N+1 queries slow the tests and production alike.

High Database
3.24 s per run
Fix: Django: fetch related rows in one query with select_related() for foreign keys and prefetch_related() for reverse/many-to-many relations, then lock the count in with assertNumQueries (or pytest-django's django_assert_num_queries).
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

Documentation

5

Make the test database server skip durability work

Tests spend 15.9s (60%) in the database. Test databases don't need to survive a crash, so the server can skip flushing to disk.

High Database
3.17 s per run
Fix: For a PostgreSQL test server (Docker/CI service) start it with -c fsync=off -c synchronous_commit=off -c full_page_writes=off, and put its data directory on tmpfs; for MySQL use --innodb-flush-log-at-trx-commit=0 --skip-log-bin. Never on a server with data you need.
Details

Only affects crash safety of the throwaway test server; query behaviour is identical.

Where:

  • apps/projects/models.py:466 save · 348 ms
  • apps/projects/profiles.py:313 write_snapshots · 258 ms
  • apps/api/tests.py:76 join_workers · 238 ms
  • apps/projects/tests.py:952 setUp · 220 ms
  • apps/api/urls.py:72 wrapped_view · 216 ms
  • apps/orgs/views.py:32 org_shell · 184 ms
  • apps/projects/profiles.py:455 write_perfs · 183 ms
  • apps/api/tests.py:73 setUp · 176 ms
  • apps/projects/models.py:35 next_number · 156 ms
  • apps/projects/profiles.py:358 claim_part · 146 ms

Most affected tests:

  • apps/api/tests.py::TestApiIndex::test_index
  • apps/projects/tests.py::SeedDemoCommandTest::test_seed_demo
  • apps/projects/tests.py::ProfilePagePaginationTest::test_slowest_tests_first_then_the_next_page
  • apps/projects/tests.py::ProjectPagesTest::test_configure_page
  • apps/api/tests.py::ProfileUploadQueueTest::test_upload_is_processed_by_the_worker
  • apps/api/tests.py::IngestStartEndpointTest::test_results_are_counted_and_the_payload_dropped
  • apps/api/tests.py::IngestStartEndpointTest::test_ingest_progress_before_start
  • apps/api/tests.py::IngestStartEndpointTest::test_all_test_status_types

Documentation

6

Stop re-running migrations on every test run

Migrations take 2.8s per run, before the first test can start.

Medium Migrations
2.56 s per run
Fix: Run with --reuse-db (add it to addopts in pytest.ini/pyproject) so the test database survives between runs; pass --create-db when migrations change. If no test depends on data migrations, --nomigrations builds the schema straight from the models, which is faster still.
Details

CI should still build the database from scratch (no --reuse-db) so broken migrations are caught.

Where:

  • apps/projects/migrations/0012_backfill_session_environments.py:30 backfill · 6 ms
  • apps/projects/migrations/0016_profile_parts.py:9 move_documents · 6 ms
  • apps/projects/migrations/0014_backfill_session_counts.py:23 backfill · 6 ms
  • apps/projects/migrations/0025_backfill_slugs_and_numbers.py:35 forwards · 3 ms
  • apps/projects/migrations/0015_store_compressed_documents_as_is.py:12 external_storage · 3 ms
  • apps/projects/migrations/0025_backfill_slugs_and_numbers.py:29 forwards · 3 ms

Most affected tests:

  • apps/api/tests.py::TestApiIndex::test_index

Documentation

7

Use a fast password hasher in tests

2.6s (10% of test time) is spent hashing passwords. Slow hashing protects real passwords; in tests it only burns CPU.

Medium Password hashing
2.48 s per run
Fix: In your test settings set PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"] (currently PBKDF2PasswordHasher).
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 · 597 ms
  • apps/orgs/tests.py:30 test_signing_up_creates_an_organization · 328 ms
  • ft/tests.py:200 test_change_password · 326 ms
  • ft/tests.py:161 test_signup · 309 ms
  • ft/tests.py:230 test_projects_only_lists_your_own_even_for_superusers · 271 ms
  • apps/orgs/tests.py:194 test_superusers_can_open_any_project_but_dont_list_them · 266 ms
  • ft/tests.py:213 test_change_password · 255 ms
  • ft/tests.py:175 setUpTestData · 255 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
  • ft/tests.py::TestAccountSettings::test_projects_only_lists_your_own_even_for_superusers
  • apps/orgs/tests.py::SuperuserTest::test_superusers_can_open_any_project_but_dont_list_them

Documentation

8

Use TestCase instead of TransactionTestCase

1.2s goes to flushing every table after tests in 11 TransactionTestCase / transaction=True / live_server tests.

Medium DB schema
1.12 s per run
Fix: Use django.test.TestCase (or @pytest.mark.django_db without transaction=True): it wraps each test in a transaction and rolls back instead of truncating every table. Keep TransactionTestCase only for tests that need real commits (on_commit hooks can use TestCase.captureOnCommitCallbacks).
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_valid
  • apps/api/tests.py::IngestStartEndpointTest::test_ingest_multiple_sessions
  • 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::IngestStartEndpointTest::test_results_are_counted_and_the_payload_dropped
  • apps/api/tests.py::IngestStartEndpointTest::test_details_are_kept_for_failures_only

Documentation

9

Tests open new database connections over and over

Connecting to the database takes 1.3s.

Medium Database
1.08 s per run
Fix: Reuse connections: create the engine once per session (not per test) and keep the default pool (NullPool reconnects on every checkout); in Django avoid closing connections in tests (connection.close()/close_old_connections).
Details

Where:

  • apps/api/tests.py:76 join_workers · 206 ms
  • apps/api/tests.py:73 setUp · 114 ms
  • apps/api/tasks.py:266 warm_reports · 70 ms
  • apps/api/urls.py:72 wrapped_view · 53 ms
  • apps/api/tests.py:212 test_ingest_start_progress_end · 34 ms
  • apps/api/tests.py:306 test_details_are_kept_for_failures_only · 25 ms
  • apps/api/tests.py:928 setUp · 24 ms
  • apps/api/tests.py:941 test_upload_is_processed_by_the_worker · 24 ms
  • apps/api/tests.py:287 test_all_test_status_types · 22 ms
  • apps/api/tests.py:257 test_ingest_end_after_progress · 22 ms

Most affected tests:

  • ft/tests.py::TestChangelogPage::test_changelog
  • apps/api/tests.py::IngestStartEndpointTest::test_all_test_status_types
  • apps/api/tests.py::IngestStartEndpointTest::test_results_are_counted_and_the_payload_dropped
  • apps/api/tests.py::IngestStartEndpointTest::test_ingest_start_progress_end
  • apps/api/tests.py::IngestStartEndpointTest::test_ingest_end_after_progress
  • apps/api/tests.py::IngestStartEndpointTest::test_ingest_progress_before_start
  • apps/api/tests.py::ProfileUploadQueueTest::test_upload_is_processed_by_the_worker
  • apps/api/tests.py::IngestStartEndpointTest::test_details_are_kept_for_failures_only
10

Create shared test data in setUpTestData instead of setUp

setUp() runs before every test and takes 844ms in total (db 777ms, library 39ms, factories 20ms) in 13 classes: SettingsTest (3 tests), ProjectsPageTest (5 tests), ProjectEditPage (6 tests), ProjectDeletePage (4 tests).

Low Database
591 ms per run
Fix: Move object creation that tests only read from setUp() into `@classmethod def setUpTestData(cls)`: it runs once per class and each test still sees the original rows (TestCase rolls back to a savepoint).
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/projects/tests.py:952 setUp · 241 ms
  • apps/api/tests.py:73 setUp · 193 ms
  • apps/projects/tests.py:1374 setUp · 62 ms
  • apps/projects/tests.py:217 setUp · 54 ms
  • apps/projects/tests.py:336 setUp · 43 ms
  • ft/tests.py:179 setUp · 41 ms
  • apps/projects/tests.py:141 setUp · 40 ms
  • apps/projects/tests.py:99 setUp · 34 ms
  • apps/projects/tests.py:267 setUp · 32 ms
  • apps/projects/tests.py:186 setUp · 31 ms

Most affected tests:

  • apps/api/tests.py::IngestStartEndpointTest::test_results_are_counted_and_the_payload_dropped
  • apps/api/tests.py::ProfileUploadQueueTest::test_upload_is_processed_by_the_worker
  • apps/api/tests.py::IngestStartEndpointTest::test_ingest_progress_before_start
  • apps/api/tests.py::IngestStartEndpointTest::test_details_are_kept_for_failures_only
  • apps/api/tests.py::IngestStartEndpointTest::test_ingest_end_after_progress
  • ft/tests.py::TestAccountSettings::test_set_password_for_github_users
  • apps/projects/tests.py::ProjectPagesTest::test_test_page
  • apps/projects/tests.py::ProjectPagesTest::test_pending_profile_page

Documentation

Tests

201–225 of 225, slowest first · click a column to sort this page
Test Outcome Duration Setup Call Teardown Mostly Queries
apps/projects/tests.py::ClassifyStreaksTest::test_dirty_runs_are_not_the_same_commit
passed 13 ms 11 ms 2 ms 0.14 ms Database 5
apps/projects/tests.py::AnalyticsTest::test_compare_environments
passed 13 ms 0.76 ms 12 ms 0.23 ms Libraries 11
apps/projects/tests.py::FlakyReportTest::test_single_test
passed 12 ms 0.72 ms 12 ms 0.20 ms Database 11
apps/projects/tests.py::StorageTest::test_slow_tests_come_from_daily_stats
passed 12 ms 0.75 ms 11 ms 0.18 ms Database 11
apps/projects/tests.py::AnalyticsTest::test_slow_tests
passed 10 ms 0.68 ms 10 ms 0.17 ms Unsampled 10
apps/projects/tests.py::AnalyticsTest::test_resolve_scope
passed 10 ms 0.70 ms 9 ms 0.17 ms Database 11
6 repeated
apps/projects/tests.py::RealProfileDocumentTest::test_entry_details
passed 10 ms 0.83 ms 8 ms 0.48 ms Database 5
apps/projects/tests.py::AnalyticsTest::test_fix_next
passed 9 ms 0.69 ms 8 ms 0.19 ms Database 8
apps/projects/tests.py::StorageTest::test_snapshot_renders_like_the_whole_document
passed 9 ms 0.72 ms 7 ms 0.72 ms Database 9
apps/projects/tests.py::AnalyticsTest::test_environment_rows
passed 8 ms 0.80 ms 7 ms 0.18 ms Database 8
apps/projects/tests.py::StorageTest::test_daily_stats_sum_the_days_results
passed 8 ms 0.73 ms 7 ms 0.18 ms Database 8
apps/projects/tests.py::AnalyticsTest::test_ci_vs_local_needs_both
passed 7 ms 0.73 ms 7 ms 0.18 ms Unsampled 9
apps/projects/tests.py::AnalyticsTest::test_suite_trend
passed 7 ms 0.63 ms 5 ms 0.65 ms Database 6
apps/projects/tests.py::RealProfileDocumentTest::test_flat_stacks_still_work
passed 5 ms 0.90 ms 4 ms 0.16 ms Unsampled 5
apps/projects/tests.py::ClassifyStreaksTest::test_environment_kinds_are_counted
passed 3 ms 0.69 ms 2 ms 0.14 ms Database 5
apps/projects/tests.py::ClassifyStreaksTest::test_test_changed_when_the_test_file_changed
passed 3 ms 0.61 ms 2 ms 0.47 ms pytest 5
apps/projects/tests.py::SlugsAndNumbersTest::test_test_slugs_read_like_their_node_ids
passed 3 ms 0.75 ms 2 ms 0.14 ms Unsampled 5
apps/projects/tests.py::ClassifyStreaksTest::test_multiple_streaks_in_order
passed 2 ms 0.65 ms 2 ms 0.14 ms Database 5
apps/projects/tests.py::ClassifyStreaksTest::test_flaky_even_if_the_pass_came_first_and_elsewhere
passed 2 ms 0.70 ms 1 ms 0.13 ms Unsampled 5
apps/projects/tests.py::ClassifyStreaksTest::test_flaky_when_failed_and_passed_on_same_commit
passed 2 ms 0.59 ms 2 ms 0.13 ms Unsampled 5
apps/projects/tests.py::ClassifyStreaksTest::test_resolved_without_changed_files
passed 2 ms 0.63 ms 1 ms 0.14 ms Unsampled 5
apps/projects/tests.py::ClassifyStreaksTest::test_regression_caught_when_app_code_fixed_it
passed 2 ms 0.60 ms 1 ms 0.12 ms Unsampled 5
apps/projects/tests.py::ClassifyStreaksTest::test_test_changed_matches_paths_relative_to_the_repository
passed 2 ms 0.65 ms 1 ms 0.14 ms Unsampled 5
apps/projects/tests.py::ClassifyStreaksTest::test_ongoing
passed 2 ms 0.66 ms 1 ms 0.12 ms Unsampled 5
apps/projects/tests.py::ClassifyStreaksTest::test_no_failures
passed 2 ms 0.63 ms 1 ms 0.12 ms Unsampled 5

Slowest fixtures

Exact setup time across the session
Fixture Scope Calls Total Max
_django_setup_unittest class 48 3.18 s 3.16 s
django_db_setup session 1 3.16 s 3.16 s
_unittest_setUpClass_fixture_ProjectPagesTest class 1 305 ms 305 ms
_unittest_setUpClass_fixture_TestAccountSettings class 1 260 ms 260 ms
_unittest_setUpClass_fixture_ProfilePagePaginationTest class 1 235 ms 235 ms
_unittest_setUpClass_fixture_McpTest class 1 218 ms 218 ms
_unittest_setUpClass_fixture_AnalyticsTest class 1 190 ms 190 ms
_unittest_setUpClass_fixture_TestChangelogPage class 1 172 ms 172 ms
_unittest_setUpClass_fixture_RealProfileDocumentTest class 1 145 ms 145 ms
_unittest_setUpClass_fixture_MemoryTest class 1 94 ms 94 ms
_unittest_setUpClass_fixture_StorageTest class 1 88 ms 88 ms
_unittest_setUpClass_fixture_FlakyReportTest class 1 74 ms 74 ms
_unittest_setUpClass_fixture_LegacyUrlTest class 1 68 ms 68 ms
_unittest_setUpClass_fixture_FlakyReportCacheTest class 1 55 ms 55 ms
_unittest_setUpClass_fixture_ProjectTestsPage class 1 23 ms 23 ms