Skip to content

Add SummaryFormatter for integration test visibility in CI - #6817

Draft
rhcarvalho wants to merge 1 commit into
phoenixframework:mainfrom
praialabs:integration-test-observability
Draft

Add SummaryFormatter for integration test visibility in CI#6817
rhcarvalho wants to merge 1 commit into
phoenixframework:mainfrom
praialabs:integration-test-observability

Conversation

@rhcarvalho

@rhcarvalho rhcarvalho commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Currently, integration tests in CI run for ~10 minutes emitting only dots (.) with no visibility into test durations.

Passing --slowest directly to mix test enables --trace, which forces --max-cases 1 (serializing all async tests) and sets timeout: :infinity.

This adds a lightweight Phoenix.Integration.SummaryFormatter that:

  1. Runs tests at full async concurrency (max_cases: 20) with active timeout protection.
  2. Automatically appends a structured Markdown summary table of all test durations (slowest to fastest) to $GITHUB_STEP_SUMMARY when running on GitHub Actions CI.
Example output runs/33211582776

Phoenix Integration Tests (Elixir 1.20.4 / OTP 29): Passed

Total Passed Failed Excluded Skipped Total Wall Time
53 53 0 0 0 7m 44s

Test Durations (Slowest to Fastest)

Status Duration Test Suite Location
passed 1m 34s test custom scope route_prefix and route_access_path with all generators AppWithScopesTest test/code_generation/app_with_scopes_test.exs:106
passed 1m 22s test phx.gen.auth generates scope for phx.gen.html AppWithScopesTest test/code_generation/app_with_scopes_test.exs:40
passed 1m 22s test phx.gen.auth generates scope for phx.gen.live AppWithScopesTest test/code_generation/app_with_scopes_test.exs:6
passed 1m 15s test phx.gen.auth generates scope for phx.gen.json AppWithScopesTest test/code_generation/app_with_scopes_test.exs:71
passed 1m 13s test phx.gen.live with scope has a passing test suite with scoped references AppWithMySqlAdapterTest test/code_generation/app_with_mysql_adapter_test.exs:96
passed 1m 06s test phx.gen.auth + argon2 has a passing test suite (--no-live) AppWithMySqlAdapterTest test/code_generation/app_with_mysql_adapter_test.exs:169
passed 1m 01s test phx.gen.json has a passing test suite AppWithMySqlAdapterTest test/code_generation/app_with_mysql_adapter_test.exs:35
passed 1m 01s test phx.gen.auth + pbkdf2 + existing context has a passing test suite AppWithMSSQLAdapterTest test/code_generation/app_with_mssql_adapter_test.exs:135
passed 1m 01s test phx.gen.json has a passing test suite AppWithSQLite3AdapterTest test/code_generation/app_with_sqlite3_adapter_test.exs:32
passed 1m 00s test phx.gen.json has a passing test suite AppWithMSSQLAdapterTest test/code_generation/app_with_mssql_adapter_test.exs:32
passed 59s test phx.gen.auth + pbkdf2 + existing context has no compilation or formatter warnings (--live) AppWithMSSQLAdapterTest test/code_generation/app_with_mssql_adapter_test.exs:86
passed 58s test phx.gen.auth + pbkdf2 + existing context has a passing test suite (--no-live) AppWithMSSQLAdapterTest test/code_generation/app_with_mssql_adapter_test.exs:160
passed 56s test phx.gen.json has a passing test suite UmbrellaAppWithDefaultsTest test/code_generation/umbrella_app_with_defaults_test.exs:100
passed 55s test phx.gen.live has a passing test suite UmbrellaAppWithDefaultsTest test/code_generation/umbrella_app_with_defaults_test.exs:152
passed 53s test custom scope phx.gen.json AppWithScopesTest test/code_generation/app_with_scopes_test.exs:571
passed 52s test phx.gen.html has a passing test suite AppWithDefaultsTest test/code_generation/app_with_defaults_test.exs:49
passed 52s test generated app boots with mix phx.server AppWithNoOptionsTest test/code_generation/app_with_no_options_test.exs:22
passed 52s test phx.gen.html has a passing test suite UmbrellaAppWithDefaultsTest test/code_generation/umbrella_app_with_defaults_test.exs:51
passed 51s test phx.gen.live has a passing test suite AppWithDefaultsTest test/code_generation/app_with_defaults_test.exs:146
passed 51s test newly generated app has no warnings or errors AppWithNoOptionsTest test/code_generation/app_with_no_options_test.exs:4
passed 51s test phx.gen.live has a passing test suite AppWithSQLite3AdapterTest test/code_generation/app_with_sqlite3_adapter_test.exs:58
passed 50s test phx.gen.live has a passing test suite AppWithMSSQLAdapterTest test/code_generation/app_with_mssql_adapter_test.exs:58
passed 50s test phx.gen.html has a passing test suite AppWithSQLite3AdapterTest test/code_generation/app_with_sqlite3_adapter_test.exs:6
passed 50s test new umbrella app has a passing test suite UmbrellaAppWithDefaultsTest test/code_generation/umbrella_app_with_defaults_test.exs:15
passed 50s test phx.gen.json has a passing test suite AppWithDefaultsTest test/code_generation/app_with_defaults_test.exs:96
passed 50s test phx.gen.html has a passing test suite AppWithMySqlAdapterTest test/code_generation/app_with_mysql_adapter_test.exs:6
passed 50s test phx.gen.html has a passing test suite AppWithMSSQLAdapterTest test/code_generation/app_with_mssql_adapter_test.exs:6
passed 49s test phx.gen.live has a passing test suite AppWithMySqlAdapterTest test/code_generation/app_with_mysql_adapter_test.exs:64
passed 48s test phx.gen.auth + bcrypt has a passing test suite (--live) AppWithSQLite3AdapterTest test/code_generation/app_with_sqlite3_adapter_test.exs:109
passed 48s test phx.gen.auth + bcrypt has a passing test suite (--no-live) AppWithSQLite3AdapterTest test/code_generation/app_with_sqlite3_adapter_test.exs:120
passed 47s test new with defaults has a passing test suite AppWithDefaultsTest test/code_generation/app_with_defaults_test.exs:15
passed 46s test phx.gen.auth + argon2 has no compilation or formatter warnings (--no-live) AppWithMySqlAdapterTest test/code_generation/app_with_mysql_adapter_test.exs:140
passed 46s test phx.gen.auth + bcrypt has no compilation or formatter warnings (--live) UmbrellaAppWithDefaultsTest test/code_generation/umbrella_app_with_defaults_test.exs:180
passed 45s test phx.gen.auth + bcrypt has no compilation or formatter warnings (--live) AppWithSQLite3AdapterTest test/code_generation/app_with_sqlite3_adapter_test.exs:86
passed 45s test phx.gen.auth + bcrypt has a passing test suite (--no-live) AppWithDefaultsTest test/code_generation/app_with_defaults_test.exs:208
passed 44s test phx.gen.auth + bcrypt has no compilation or formatter warnings (--no-live) AppWithSQLite3AdapterTest test/code_generation/app_with_sqlite3_adapter_test.exs:97
passed 42s test phx.gen.html has no compilation or formatter warnings AppWithDefaultsTest test/code_generation/app_with_defaults_test.exs:26
passed 41s test phx.gen.auth + pbkdf2 + existing context has no compilation or formatter warnings (--no-live) AppWithMSSQLAdapterTest test/code_generation/app_with_mssql_adapter_test.exs:110
passed 41s test phx.gen.json has no compilation or formatter warnings UmbrellaAppWithDefaultsTest test/code_generation/umbrella_app_with_defaults_test.exs:76
passed 40s test phx.gen.html has no compilation or formatter warnings UmbrellaAppWithDefaultsTest test/code_generation/umbrella_app_with_defaults_test.exs:27
passed 39s test new with defaults has no compilation or formatter warnings AppWithDefaultsTest test/code_generation/app_with_defaults_test.exs:5
passed 38s test new umbrella app has no compilation or formatter warnings UmbrellaAppWithDefaultsTest test/code_generation/umbrella_app_with_defaults_test.exs:5
passed 37s test phx.gen.auth + argon2 has a passing test suite (--live) AppWithMySqlAdapterTest test/code_generation/app_with_mysql_adapter_test.exs:156
passed 37s test phx.gen.auth + argon2 has no compilation or formatter warnings (--live) AppWithMySqlAdapterTest test/code_generation/app_with_mysql_adapter_test.exs:128
passed 37s test phx.gen.auth + bcrypt has a passing test suite --no-live UmbrellaAppWithDefaultsTest test/code_generation/umbrella_app_with_defaults_test.exs:218
passed 35s test phx.gen.json has no compilation or formatter warnings AppWithDefaultsTest test/code_generation/app_with_defaults_test.exs:73
passed 34s test phx.gen.auth + bcrypt has no compilation or formatter warnings (--live) AppWithDefaultsTest test/code_generation/app_with_defaults_test.exs:173
passed 30s test phx.gen.auth + bcrypt has a passing test suite (--live) AppWithDefaultsTest test/code_generation/app_with_defaults_test.exs:196
passed 26s test phx.gen.auth + bcrypt has a passing test suite --live UmbrellaAppWithDefaultsTest test/code_generation/umbrella_app_with_defaults_test.exs:205
passed 14s test phx.gen.auth + bcrypt has no compilation or formatter warnings (--no-live) AppWithDefaultsTest test/code_generation/app_with_defaults_test.exs:184
passed 13s test phx.gen.live has no compilation or formatter warnings UmbrellaAppWithDefaultsTest test/code_generation/umbrella_app_with_defaults_test.exs:125
passed 13s test phx.gen.live has no compilation or formatter warnings AppWithDefaultsTest test/code_generation/app_with_defaults_test.exs:120
passed 10s test phx.gen.auth + bcrypt has no compilation or formatter warnings (--no-live) UmbrellaAppWithDefaultsTest test/code_generation/umbrella_app_with_defaults_test.exs:192

Currently, integration tests in CI run for ~10 minutes emitting only
dots (`.`) with no visibility into test durations.

Passing `--slowest` directly to `mix test` enables `--trace`, which
forces `--max-cases 1` (serializing all async tests) and sets
`timeout: :infinity`.

This adds a lightweight `Phoenix.Integration.SummaryFormatter` that:
1. Runs tests at full async concurrency (`max_cases: 20`) with active
   timeout protection.
2. Automatically appends a structured Markdown summary table of all test
   durations (slowest to fastest) to `$GITHUB_STEP_SUMMARY` when running on
   GitHub Actions CI.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant