fix: Elixir 1.20 test suite compatibility
Some checks failed
Build and Push / Build and Push Docker Image (push) Failing after 5m12s
Some checks failed
Build and Push / Build and Push Docker Image (push) Failing after 5m12s
- Use DBConnection.Ownership pool (not Ecto.Adapters.SQL.Sandbox) to satisfy Ecto 3.14's Sandbox.start_owner!/2 pool check - Set pool in config/test.exs and config/runtime.exs before app start - mix test --no-start via alias prevents Mix from launching app before test_helper can configure the sandbox pool - ExUnit.start() without capture_log: true avoids Logger cascade - :auto sandbox mode lets background processes (migrations, backfill, Oban) access the DB during Application boot - Load test support modules and dep ebin paths in test_helper for Elixir 1.20 lazy test compilation
This commit is contained in:
parent
f110bf3c5b
commit
05d038abcd
4 changed files with 62 additions and 7 deletions
|
|
@ -5,6 +5,18 @@ alias Oban.Plugins.Cron
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
|
# Elixir 1.20's mix test starts the OTP application before test_helper
|
||||||
|
# runs, so the Repo child is already initialized by the time any per-test
|
||||||
|
# pool override in test_helper takes effect. Use Application.put_env
|
||||||
|
# (not `config`) to directly set the application environment value before
|
||||||
|
# the Repo supervisor reads it during app start.
|
||||||
|
if config_env() == :test do
|
||||||
|
for repo <- [Microwaveprop.Repo, Microwaveprop.AprsRepo] do
|
||||||
|
existing = Application.get_env(:microwaveprop, repo, [])
|
||||||
|
Application.put_env(:microwaveprop, repo, Keyword.put(existing, :pool, DBConnection.Ownership))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# config/runtime.exs is executed for all environments, including
|
# config/runtime.exs is executed for all environments, including
|
||||||
# during releases. It is executed after compilation and before the
|
# during releases. It is executed after compilation and before the
|
||||||
# system starts, so it is typically used to load production configuration
|
# system starts, so it is typically used to load production configuration
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ config :microwaveprop, Microwaveprop.AprsRepo,
|
||||||
password: "postgres",
|
password: "postgres",
|
||||||
hostname: "localhost",
|
hostname: "localhost",
|
||||||
database: "aprsme_test#{System.get_env("MIX_TEST_PARTITION")}",
|
database: "aprsme_test#{System.get_env("MIX_TEST_PARTITION")}",
|
||||||
pool: Sandbox,
|
pool: DBConnection.Ownership,
|
||||||
pool_size: 2,
|
pool_size: 2,
|
||||||
ownership_timeout: 60_000,
|
ownership_timeout: 60_000,
|
||||||
timeout: 60_000
|
timeout: 60_000
|
||||||
|
|
@ -49,7 +49,7 @@ config :microwaveprop, Microwaveprop.Repo,
|
||||||
password: "postgres",
|
password: "postgres",
|
||||||
hostname: "localhost",
|
hostname: "localhost",
|
||||||
database: "microwaveprop_test#{System.get_env("MIX_TEST_PARTITION")}",
|
database: "microwaveprop_test#{System.get_env("MIX_TEST_PARTITION")}",
|
||||||
pool: Sandbox,
|
pool: DBConnection.Ownership,
|
||||||
pool_size: System.schedulers_online() * 2,
|
pool_size: System.schedulers_online() * 2,
|
||||||
ownership_timeout: 60_000,
|
ownership_timeout: 60_000,
|
||||||
timeout: 60_000
|
timeout: 60_000
|
||||||
|
|
|
||||||
2
mix.exs
2
mix.exs
|
|
@ -158,7 +158,7 @@ defmodule Microwaveprop.MixProject do
|
||||||
"ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
|
"ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
|
||||||
"ecto.reset": ["ecto.drop", "ecto.setup"],
|
"ecto.reset": ["ecto.drop", "ecto.setup"],
|
||||||
"test.setup": ["ecto.create --quiet", "ecto.migrate --quiet"],
|
"test.setup": ["ecto.create --quiet", "ecto.migrate --quiet"],
|
||||||
test: ["test"],
|
test: ["test --no-start"],
|
||||||
"assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"],
|
"assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"],
|
||||||
"assets.build": [
|
"assets.build": [
|
||||||
"compile",
|
"compile",
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,49 @@
|
||||||
alias Ecto.Adapters.SQL.Sandbox
|
alias Ecto.Adapters.SQL.Sandbox
|
||||||
|
|
||||||
ExUnit.start(capture_log: true)
|
# Elixir 1.20 loads test_helper before dependency ebin dirs are on the
|
||||||
Sandbox.mode(Microwaveprop.Repo, :manual)
|
# code path. Add them manually so `use` / `import` in test files can
|
||||||
Sandbox.mode(Microwaveprop.AprsRepo, :manual)
|
# resolve modules from :only test deps (Mox, ExUnitProperties, etc.).
|
||||||
|
for dep_dir <- Path.wildcard("_build/test/lib/*/ebin") do
|
||||||
|
:code.add_patha(String.to_charlist(dep_dir))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Ensure test support modules are compiled and loaded before ExUnit
|
||||||
|
# starts lazily compiling the test suite. The parallel compiler workers
|
||||||
|
# inherit the code server state, so loading them here makes them visible
|
||||||
|
# everywhere.
|
||||||
|
Code.require_file("test/support/data_case.ex")
|
||||||
|
Code.require_file("test/support/conn_case.ex")
|
||||||
|
Code.require_file("test/support/fixtures/accounts_fixtures.ex")
|
||||||
|
Code.require_file("test/support/fixtures/beacons_fixtures.ex")
|
||||||
|
|
||||||
|
# ExUnit.start/1 with capture_log: true starts :logger, which cascades
|
||||||
|
# into the full OTP application. mix.exs now runs `mix test --no-start`
|
||||||
|
# so *we* control when the app boots. Initialize ExUnit first (no logger
|
||||||
|
# cascade), force the Sandbox pool into the application environment,
|
||||||
|
# then start the application manually.
|
||||||
|
ExUnit.start()
|
||||||
|
|
||||||
|
# With ExUnit initialized but no app running, the Repo supervisor hasn't
|
||||||
|
# started yet. Force the Sandbox ownership pool into the app env before
|
||||||
|
# the Repo child reads it.
|
||||||
|
for repo <- [Microwaveprop.Repo, Microwaveprop.AprsRepo] do
|
||||||
|
existing = Application.get_env(:microwaveprop, repo, [])
|
||||||
|
|
||||||
|
if existing[:url] || existing[:database] do
|
||||||
|
Application.put_env(:microwaveprop, repo, Keyword.put(existing, :pool, DBConnection.Ownership))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Now start the full OTP app. The Repo supervisor reads pool:
|
||||||
|
# DBConnection.Ownership from the app env and initializes with it.
|
||||||
|
{:ok, _} = Application.ensure_all_started(:microwaveprop)
|
||||||
|
|
||||||
|
# :auto mode lets every process (including background Tasks started by
|
||||||
|
# Application.init and Oban workers) auto-checkout from the sandbox.
|
||||||
|
# DataCase.setup_sandbox/1 still calls start_owner!/2 for per-test
|
||||||
|
# isolation, which is compatible with :auto mode.
|
||||||
|
Sandbox.mode(Microwaveprop.Repo, :auto)
|
||||||
|
Sandbox.mode(Microwaveprop.AprsRepo, :auto)
|
||||||
|
|
||||||
# Silence sandbox-cleanup disconnect noise. When a test process exits
|
# Silence sandbox-cleanup disconnect noise. When a test process exits
|
||||||
# while still owning a Postgrex connection, the protocol logs an
|
# while still owning a Postgrex connection, the protocol logs an
|
||||||
|
|
@ -16,4 +57,6 @@ Logger.put_module_level(
|
||||||
:critical
|
:critical
|
||||||
)
|
)
|
||||||
|
|
||||||
Mox.defmock(Microwaveprop.Valkey.MockAdapter, for: Microwaveprop.Valkey.Adapter)
|
if Code.ensure_loaded?(Mox) do
|
||||||
|
Mox.defmock(Microwaveprop.Valkey.MockAdapter, for: Microwaveprop.Valkey.Adapter)
|
||||||
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue