Skip to content

Add trace helper to ExUnit.Assertions#15432

Merged
josevalim merged 7 commits into
elixir-lang:mainfrom
SteffenDE:sd-exunit-trace
Jun 8, 2026
Merged

Add trace helper to ExUnit.Assertions#15432
josevalim merged 7 commits into
elixir-lang:mainfrom
SteffenDE:sd-exunit-trace

Conversation

@SteffenDE

Copy link
Copy Markdown
Contributor

This started in phoenixframework/phoenix_live_view#4242.

Imagine that you are testing a LiveView (or any process like a GenServer) that is subscribed to messages from another process (could be Phoenix PubSub). In a test, you trigger a process that will eventually deliver that message (but you don't control the exact timing), and you need to assert on the rendered result of the LiveView (GenServer state):

test "handles work", %{conn: conn} do
  {:ok, view, _html} = live(conn, "/path")

  Something.do_work() # the LiveView is subscribed to events emitted by do_work

  assert render(view) =~ "work done"
end

If there's no guarantee that the LiveView already received the message from do_work when calling render, this test is flaky. For example, if another process is involved, scheduling might cause the message to arrive only after the render GenServer call.

One workaround would be to retry the assertion, which arguably is not a nice solution:

assert Enum.reduce_while(1..10, fn _i, _acc ->
  if render(view) =~ "work done" do
    {:halt, true}
  else
    {:cont, false}
  end
end)

By introducing a trace helper, the test can ensure that the LiveView handled the message before it asserts on its rendered state:

test "handles work", %{conn: conn} do
  {:ok, view, _html} = live(conn, "/path")

  trace(view.pid, [:receive], fn ->
    Something.do_work() # the LiveView is subscribed to events emitted by do_work
    assert_receive {:trace, _, :receive, {:work, :foo}} # the message that updates the state to work done 
    assert render(view) =~ "work done"
  end)
end

This PR adds a new trace/3 (and trace/4) helper to ExUnit.Assertions, implemented as a light wrapper around Erlang's :trace sessions, introduced in OTP 27.

Comment thread lib/ex_unit/lib/ex_unit/assertions.ex Outdated
Comment thread lib/ex_unit/lib/ex_unit/assertions.ex Outdated
Comment thread lib/ex_unit/lib/ex_unit/assertions.ex Outdated
Comment thread lib/ex_unit/lib/ex_unit/assertions.ex Outdated
@SteffenDE SteffenDE marked this pull request as ready for review June 8, 2026 09:46
Comment thread lib/ex_unit/lib/ex_unit/assertions.ex Outdated
Comment thread lib/ex_unit/lib/ex_unit/assertions.ex Outdated
@josevalim josevalim merged commit 1cb62b7 into elixir-lang:main Jun 8, 2026
15 checks passed
@josevalim

Copy link
Copy Markdown
Member

💚 💙 💜 💛 ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants