Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix Now×
Skip to content
World desk5 min

How to Test Elixir OTP Processes and Supervision Trees

Use ExUnit’s test supervisor for process cleanup, public APIs for GenServer behavior, and controlled exits plus PID assertions to verify OTP restart contracts.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use ExUnit’s test supervisor to give each test a fresh process, exercise GenServers through their public APIs, and test supervision by triggering a controlled failure and checking the configured restart behavior. The right assertion depends on what you need to prove: a reply, a message, a termination reason, a restarted PID, or the effect on sibling children.

The examples below are illustrative; adapt child IDs, APIs and failure triggers to your application. Elixir’s documentation index reported v1.20.4 as stable on 2026-10-04, while some linked API pages are versioned earlier. Use documentation matching the Elixir version pinned by your project.

How do I start a process in ExUnit and clean it up?

Prefer ExUnit’s test-supervised helpers to starting a linked process directly in each test. A child started with start_supervised/2 is owned by the test supervisor and is stopped before the next test begins, which gives process setup and cleanup a clear boundary. The helper does not link the child to the test process, so an unexpected child crash does not necessarily fail the test.

Use the raising variant when a failed startup should fail setup immediately:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
use ExUnit.Case, async: true

setup do
  server = start_supervised!({MyApp.Counter, 0})
  %{server: server}
end

test "increments the counter", %{server: server} do
  assert MyApp.Counter.value(server) == 0
  assert MyApp.Counter.increment(server) == 1
end

The module and arguments must fit the process’s child specification and start_link contract. ExUnit.Callbacks documentation describes the test-supervised helpers and cleanup behavior.

  • start_supervised!/2 raises on startup failure and returns the PID.
  • start_supervised/2 returns a startup result such as {:ok, pid} or {:error, reason}, useful when the result itself is under test.
  • start_link_supervised!/2 links the child to the test process; use it when a child crash should propagate and fail the test.
  • stop_supervised/1 removes a child before the test ends. Simply terminating a restartable child may cause its supervisor to start it again.

Choose the helper according to the failure contract: an unlinked child is convenient for isolated ownership, while a link makes unexpected termination consequential to the test.

How do I test a GenServer in Elixir?

Test ordinary GenServer behavior through the same public API that callers use. Assert replies or observable state transitions rather than private callback details; callbacks are implementation details unless the callback behavior itself is part of the contract. The GenServer guide demonstrates client-server testing and test-supervised startup.

  • For synchronous operations, assert the returned value.
  • For asynchronous output that callers are meant to receive, use assert_receive with a bounded timeout.
  • For termination behavior, monitor the process and assert the resulting :DOWN message and reason.
  • Avoid arbitrary sleeps as synchronization. A reply, expected message, or monitor signal gives the test an observable event to wait for.

Monitoring and linking prove different things. A monitor lets the test assert that a process ended and why; a link makes an unexpected exit reach the test process. Use the mechanism that matches the behavior being specified.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How do I test that a supervisor restarts a process?

Start the supervisor or relevant subtree under the test supervisor, identify the child by its child ID, then cause a controlled failure and assert the result. A child specification determines its start, shutdown and restart behavior, while the supervision strategy determines which other children are affected. See the versioned Supervisor documentation.

Account for restart mode and exit reason

  • :permanent children restart regardless of exit reason.
  • :transient children restart after abnormal exits, but not normal termination.
  • :temporary children do not restart.

Therefore, an intentional normal stop does not test a transient child’s abnormal-exit restart path. Trigger the relevant kind of exit deliberately and assert the behavior promised by the child specification.

Account for the supervision strategy

  • :one_for_one: the failed child is restarted; unaffected siblings remain.
  • :one_for_all: failure causes all children in the group to be restarted.
  • :rest_for_one: the failed child and children started after it are restarted.

Check PIDs before and after the failure to verify which children were replaced. For the restarted child, a new PID and a known initialized result are useful observable assertions. When child modules can appear more than once, capture children using their IDs or unique test names rather than assuming the module identifies one child.

Use an observable restart signal

A restart test should not guess completion with a sleep. Use an explicit test-visible signal, a suitable supervisor or monitoring event, or another synchronization point exposed by the application. One possible pattern is:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
test "restarts a permanent worker after an abnormal exit" do
  supervisor = start_supervised!({MyApp.WorkerSupervisor, []})
  old_pid = MyApp.WorkerSupervisor.worker_pid(supervisor)

  send(old_pid, :crash_for_test)
  assert_receive {:worker_restarted, new_pid}

  refute old_pid == new_pid
  assert MyApp.Worker.get_state(new_pid) == :initial_state
end

This sketch assumes the application provides the worker lookup, controlled trigger and restart notification shown. Those are not universal OTP APIs; adapt the test to the real contract rather than adding a brittle production-only hook without need.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

How do I test a DynamicSupervisor?

Start a fresh DynamicSupervisor for the test, then add and remove children through its API. Assert that a child is present after a successful start and absent after a stop or termination consistent with its restart mode. The outer ExUnit test supervisor supplies lifecycle cleanup for the test’s processes. The DynamicSupervisor guide covers the API; check it against the project’s pinned Elixir version.

Which assertion method should I use?

Test need Mechanism What it establishes
Validate ordinary server behavior Call the public API and assert its reply or observable state The caller-facing process contract works
Observe asynchronous output assert_receive with a bounded timeout The expected message was emitted
Verify a process ended Monitor and assert the :DOWN reason The process terminated with the expected reason
Make child crashes fail the test start_link_supervised!/2 A linked child’s exit reaches the test process
Ensure test-owned child cleanup start_supervised!/2 The test supervisor stops the child at test completion
Verify restart policy Controlled exit followed by PID and behavior assertions The child restart contract was applied
Verify sibling effects Capture sibling PIDs before and after failure The configured strategy’s effect on siblings

When should these tests run asynchronously?

async: true is appropriate only when concurrent tests cannot interfere through shared resources. A separate process per test does not isolate registered names, shared mutable state, files, ports, external services or other global resources. Use unique names and per-test resources, or disable async execution for tests that share state. ExUnit’s helper documentation describes test lifecycle behavior; the GenServer guide discusses testing process behavior.

ExUnit capabilities can vary by release, including grouping and parameterized runs documented in newer versions. Confirm feature availability against the Elixir version your project pins. The Elixir documentation index reported v1.20.4 as stable on 2026-10-04 and listed Erlang/OTP 27, 28 and 29 as supported at that time.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.