Supertester Logo

Hex.pm Documentation Build Status License

Supertester is an OTP-focused testing toolkit for Elixir. It helps you write deterministic tests for concurrent systems without Process.sleep/1, while keeping tests async-safe through per-test isolation.

Version: 0.6.0

Installation

def deps do
  [
    {:supertester, "~> 0.6.0", only: :test}
  ]
end
mix deps.get

Quick Example

defmodule MyApp.CounterTest do
  use Supertester.ExUnitFoundation, isolation: :full_isolation

  import Supertester.{OTPHelpers, GenServerHelpers, Assertions}

  test "increments deterministically" do
    {:ok, counter} = setup_isolated_genserver(Counter)

    :ok = cast_and_sync(counter, :increment)

    assert_genserver_state(counter, fn state -> state.count == 1 end)
  end
end

Core Modules

Behavioral Notes

  • cast_and_sync/4
    • When the sync handler replies :ok (the default TestableGenServer behavior), returns bare :ok.
    • When the sync handler replies with any other value (including error tuples), returns {:ok, reply}.
    • strict?: true raises ArgumentError when synchronization support is missing.
    • Non-strict mode returns {:error, :missing_sync_handler} when missing.
  • test_restart_strategy/3
    • validates expected supervisor strategy and raises on mismatch.
    • raises ArgumentError when scenario child IDs are unknown.
    • temporary removed children are not reported as restarted.
  • chaos_kill_children/2
    • accepts pid or registered supervisor name (atom, {:global, _}, {:via, _, _}).
    • restarted counts observed child replacements, including cascade replacements.
  • run_chaos_suite/3
    • applies a suite-level timeout.
    • only true per-scenario deadline overruns are treated as timeout cutoffs.
    • scenarios that independently return {:error, :timeout} do not stop the suite.
  • assert_no_process_leaks/1
    • tracks spawned/linked processes attributable to the operation.
    • catches delayed descendant leaks.
    • avoids flagging short-lived transient processes as leaks.

Safety

  • No unbounded dynamic atom creation is used for test IDs or isolation naming paths.
  • ETS fallback injection (ETSIsolation.inject_table/3-4) uses existing atoms only and raises instead of creating dynamic atoms.

Documentation

Examples

License

MIT