How to clean up after each test inside describe?

Background

I have a test file with several describe blocks, each one with a custom setup block, like the following:

defmodule MyAppTest do
  use ExUnit.Case

  describe "group 1" do
    
    setup do
      :persistent_term.put("hello", :world)
      :ok
    end

    test "test 1" do
      assert true
    end

    test "test 2" do
      assert true
    end

  end

# describe group2 ....

end

Here I am setting up a persistent term that I will use along the app. Now, once I reach the end of all tests in the describe block, I want to clean up, meaning I want to delete the "hello" entry from :persistent_term.

To achieve this I am aware of on_exit, but according to my understanding, this callback is only executed once at the end of all tests from all describe blocks.

Questions

  1. Is my understanding of on_exit correct?
  2. How can I run a clean up function after the tests of each describe block?

:wave:

on_exit in a setup block is executed after each test, in my experience. I’ve never tried using on_exit in setup_all though.

According to my understanding and in my specific example, setup will only be executed once per describe block. What I am looking for is a on_exit that is executed once per describe block as well.

setup is always executed per test and on_exit will always respect the context it is called in. On exit in setup runs after the test. On setup all, after all tests, etc.

5 Likes

Ahh, so in my example, I am actually running :persistent_term.put("hello", :world) each time I run a test, and not once per describe block, right?

Will the current code run :persistent_term.put("hello", :world) once per each test inside the given describe block, or once per each test independently?

It will run once for each test in the describe block. But since it is a side-effect, it will be leaked to other tests.

1 Like

I see. This open an interesting discussion (for another post).

Last set of questions:

  1. If I use setup_all inside a describe block, it will ignore it, correct? (meaning it will run as if it wasn’t inside a block, before all tests in the file)
  2. How do I use on_exit with setup all? Could someone give me an example? (I have trouble understanding the docs)

it will ignore it, correct?

If I understand the source correctly it won’t even compile.

Could someone give me an example?

i.e. it doesn’t look like it is any different from using on_exit/1 inside a regular setup block. on_exit registers a function to perform the teardown (and if the function is created inside the block is has access to anything inside of the block).