ExUnit: Passing context from one test to another?

For example, I want to test an insert and an update to a database.

I need the database generated id from the result of the insert test to do the update test.

I see that ExUnit has setup methods that allow setting up a “context” that will be passed to tests.

However, is it possible to pass some results of one test to another test?

Also, and/or is it possible to do a setup between tests?

Example of what I’m talking about

What I’d like to do if tests could update the context for next tests:

defmodule InsertUpdateTest do
  use ExUnit.Case

  setup do
    # setup database stuff
  end

  test "insert works", _context do
    my_record = %{ name: "a record" }
    insert_result = InsertUpdate.insert( my_record )
    assert {:ok, %{ id: id} } = insert_result
    {:ok, %{ id: id } } # << context would be updated to include id
  end

  test "update works", context do
    %{id: id} = context # << getting the id from context that was set from the insert test
    # ... the rest of the test that uses the id for updating
  end
end

Another way if the above is not possible:

defmodule InsertUpdateTest do
  use ExUnit.Case

  setup do
    # setup database stuff
  end

  test "insert works", _context do
    my_record = %{ name: "a record" }
    insert_result = InsertUpdate.insert( my_record )
    assert {:ok, %{ id: id} } = insert_result
  end

  setup do
    # basically just do another insert since only(?) setup calls can change context
    my_record = %{ name: "a record" }
    {:ok, %{ id: id} } = InsertUpdate.insert( my_record )
    %{ id: id}  # << update context here using this id instead
  end

  test "update works", context do
    %{id: id} = context # << getting the id from context that was set from the setup method
    # ... the rest of the test that uses the id for updating
  end

  setup do
    # can I further change the context here so that the changes
    # apply only to "another test" below?
  end

  test "another test", context do
    # ...
  end
end

While it seems convenient to couple tests like this you should probably keep your tests self contained. Changing something in your insert test should not affect your update test.

3 Likes

Also tests should be running in parallel…

I see.

So, the best practice recommendation would be to separate the insert test and the update test into separate test cases (separate .exs files)?

Separate test cases yes, but no need to be in different .exs files.

1 Like

This is an old topic, but also something I wanted to do. I’d like to run some simple integration tests using Exunit. The first test would call an API to log a verification request. It would be nice to pass the verification ID it receives along to the following test, so it can be used in the next API call. I could combine it all in one test, but it looks a little ugly.

Instead of passing the ID from one test to the next test, create a setup helper, which fetches another ID independently as part of the second tests setup.

1 Like