6

I'd like to reuse the same code of a test case for several handcrafted combinations of input data and expected outcomes, but without copypasting the code for each set. Frameworks in other languages support it in different ways, for example in Groovy/Spock:

def "maximum of two numbers"(int a, int b, int c) {
        expect:
        Math.max(a, b) == c

        where:
        a | b | c
        1 | 3 | 3
        7 | 4 | 4
        0 | 0 | 0
}

What's the preferred way to do this in ExUnit? Maybe ExUnit is not the best framework to this?

2 Answers2

8

I guess you could do something very simple like:

test "Math.max/2" do
  data = [
    {1, 3, 3},
    {7, 4, 4},
  ]

  for {a, b, c} <- data do
    assert Math.max(b, c) == a
  end
end

Pattern matching allows you to be pretty explicit when doing these thing in my opinion. And you can keep the simplicity of just variables and assertions, all inside ExUnit.

whatyouhide
  • 15,897
  • 9
  • 57
  • 71
  • The problem I see with this approach is that if any of the examples fails, you get the whole test failing. – MachinesAreUs May 08 '15 at 15:14
  • @MachinesAreUs true, but ExUnit does an amazing job at telling you what went wrong thanks to `assert` being a macro (and printing the code you're testing). You would see `Math.max/2 failed` but you would still be able to see what case failed. The only downside I can think of is that you'll see only one error at the time; if that's important to you, go with @FredtheMagicWonderDog's solution. – whatyouhide May 09 '15 at 15:16
7

You can also wrap test definitions with an enumerable. Dave Thomas's Blog provides an extended example.

data = [
  {1, 3, 3},
  {7, 4, 4},
]

for {a,b,c} <- data do
  @a a
  @b b
  @c c
  test "func "<>@a<>", "<>@b<>" equals"<>@c do  
    assert fun(@a,@b) == @c 
  end
end

For a relatively simple test like this, I'm not sure this approach is any better, but for more complex tests this can provide better reporting and you can dynamically create tests at test time by using a function as in the blog entry.