StatifierPersistence.Testing.StorageConformance (StatifierPersistence v0.1.0)

Copy Markdown View Source

The conformance suite every StatifierPersistence.Storage.Adapter must pass. Ships in lib/ (ADR-0003 decision 5, st-ADR-0053's shape) so an adapter in another package runs the identical suite:

defmodule MyApp.EctoAdapterConformanceTest do
  use StatifierPersistence.Testing.StorageConformance,
    adapter: MyApp.EctoAdapter,
    opts: [repo: MyApp.Repo]
end

Every test generated here goes through either the adapter directly (the callbacks in StatifierPersistence.Storage.Adapter) or through StatifierPersistence.Storage, the guarded facade every adapter sits behind. Nothing here reaches into test/ - the fixtures come from StatifierPersistence.Testing.Charts, the sibling module this one is named alongside, so the one-way StatifierPersistence.Testing.* rule (ADR-0003 decision 5) holds for both.

init/1 is called once per test, in setup, so every generated test starts from a fresh handle. When the adapter under test exports the optional StatifierPersistence.Storage.Adapter.isolate/1 callback, setup calls it right after init/1 - the hook an adapter backed by a shared resource (a database connection, a sandbox checkout) uses to wrap the test that follows in its own isolated unit. An adapter that exports no such callback, like StatifierPersistence.Storage.InMemory, is unaffected: the check is a function_exported?/3 guard, not a requirement.

The optional StatifierPersistence.Storage.Adapter.lock_run/3 gets the same treatment at generation time: when the adapter under test exports it, the suite generates the per-run lock tests (mutual exclusion of two concurrent bodies, release after a raising fun); when it does not, they are not generated at all - exporting the callback is what opts an adapter into its contract.