Skip to content

Make test suites generated by phx.gen.auth use async: true - #5689

Merged
josevalim merged 1 commit into
phoenixframework:mainfrom
goncalotomas:make-auth-test-suites-use-async-true
Jan 6, 2024
Merged

Make test suites generated by phx.gen.auth use async: true#5689
josevalim merged 1 commit into
phoenixframework:mainfrom
goncalotomas:make-auth-test-suites-use-async-true

Conversation

@goncalotomas

Copy link
Copy Markdown
Contributor

Test suites generated by mix phx.gen.auth conditionally set async: true if the database adapter is Postgres. Some of those test suites are missing that condition despite no apparent issues running tests concurrently.

I used these steps to test this out:

  • Created a simple demo app using mix phx.new
  • Add authentication code using mix phx.gen.auth Accounts User users and run migrations
  • Run for X in 1 2 3 4 5 6 7 8 9 10; do mix test; done

I've ran these tests many times and I did not see any failures.
Originally posed as a question here, pinging @josevalim as requested :)

@josevalim
josevalim merged commit 3d609e0 into phoenixframework:main Jan 6, 2024
@josevalim

Copy link
Copy Markdown
Member

💚 💙 💜 💛 ❤️

@goncalotomas
goncalotomas deleted the make-auth-test-suites-use-async-true branch January 21, 2024 10:18
SteffenDE pushed a commit that referenced this pull request Aug 2, 2026
… apps (#6783)

Fixes a long-standing flaky test issue in generated SQLite applications where
running `mix test` would intermittently fail with:

    ** (Exqlite.Error) Database busy

Root Cause

`phx.new` generated `error_html_test.exs` and `error_json_test.exs` with
hardcoded `use ConnCase, async: true`.

In apps with Ecto enabled, `ConnCase` includes a setup block that calls
`DataCase.setup_sandbox(tags)`. When ExUnit runs an `async: true` test module
concurrently with `async: false` test modules (such as tests generated by
`phx.gen.auth`), `setup_sandbox` sees `tags[:async] == true` and checks out
a non-shared secondary connection handle (`shared: false`) from the Repo pool.

Because SQLite uses single-file database locking, having two active database
connections opening sandbox transactions concurrently causes file lock contention
whenever a synchronous test inserts records (e.g. `user_fixture()`). Depending
on ExUnit test seeding and process scheduling, the secondary connection checkout
fails with `(Exqlite.Error) Database busy`.

Background

When `--database sqlite3` support was added in 5143696
(#4268, April 2021), error controller test templates retained hardcoded
`use ConnCase, async: true`. Later, when `phx.gen.auth` introduced support for
`async: true` in 3d609e0 (#5689, January 2024),
it added a helper to conditionally append `async: true` ONLY for PostgreSQL adapters
while leaving non-Postgres adapters as `async: false`. However, `phx.new` was not
updated at the time to use the same logic for its generated error test templates.

Fix

1. Add `test_case_options/1` in `Phx.New.Generator` matching the behavior of `phx.gen.auth`:
   - `Ecto.Adapters.Postgres` -> `", async: true"`
   - `nil` (no Ecto) -> `", async: true"`
   - non-Postgres adapters (SQLite, MySQL, TDS) -> `""`

2. Update `error_html_test.exs.eex` and `error_json_test.exs.eex` templates to use `<%= @test_case_options %>`.

3. Added test coverage across single app and umbrella project generators for Postgres, `--no-ecto`, SQLite3, MySQL, and MSSQL.
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.

2 participants