SetUp and TearDown in Test module?

Hello everyone,

I’m still quite new to Julia, so please excuse me if I have missed something obvious here. Is there a way in Test.jl to declare functions that are called before/after every @testset similar to SetUp/TearDown methods in other languages like C++ or Python? If there isn’t, are there best practices on implementing something similar for a test suit?

1 Like

The easiest way is to just put the @testests in functions, and then call them from a loop. For a very simple example

function test1(x)
     @test x[1]=1
end

function test2(x)
     @test x[2]==2
     x .= 0 #thing that requires cleanup
end

for f in [test1,test2]
    x = [1,2] # setup
    f(x)
    #add teardown here if needed
end

The reason Julia doesn’t need Setup and Teardown is that unlike other languages, it is very idiomatic to treat functions as objects and do higher order programming. (most testing interfaces traditionally were inspired by Java which makes higher order functions a total pain).

4 Likes

You can use a do block.

function test()
    setupteardown() do 
    end
end
2 Likes

@jzr offers a good suggestion, so let’s expand to make it more explicit. The do-notation does make setup and teardown pretty. If you want to isolate tests, the SafeTestsets.jl package defines a different macro for the unit test, to create an automatic module for it. This can make it hard to load a package macro in the test, but it usually works fine. It does mean you have to define helper functions inside a module so that they can be loaded. It’s not difficult in practice and looks like this.

module TestHelpers
  function setupteardown(f)
    resources = ...setup...
    try
      f(resources)
    finally
      ...teardown...
    end
  end
end
@safetestset "this invariant is true" begin
  using ..TestHelpers
  setupteardown() do resources
    @test any(resources)
  end
end

You can put your setup and teardown helpers into another file, as long as you include it before the tests in the runtests.jl file.

4 Likes

Wow, thanks for the quick answers and clarifications! I’ll try and implement it in do notation then.