How to inject a variable into a test scope?

I want to generate a set of tests based on some external file, and avoid typing them out .

I would hope that this would work:

for {test_name, input, output} <- get_specs() do
  test "test #{test_name}" do
   assert process(input) == output
  end
end

But the compiler complains that input and output are unknown.

I tried doing this with a macro:

defmacro test_row(test_name, input, output) do
   quote do
     test "test #{test_name}" do
       assert process(unquote(input)) == unquote(output)
     end
   end
end

for {test_name, input, output} <- get_specs() do
  test_row(test_name, input, output)
end

But then the compiler complains about not being able to find test_row.

I have found a workaround by using module variables:

for {test_name, input, output} <- get_specs() do
  @input input
  @output output
  test "test #{test_name}" do
   assert process(@input) == @output
  end
end

But it looks a bit ugly. So I wonder, is there a “canonical” way of doing this sort of thing?

You’re nearly there, just a small change since test is a macro. Start with your first effort and then unquote the bindings from the outer scope:

for {test_name, input, output} <- get_specs() do
  test "test #{test_name}" do
   assert process(unquote(input)) == unquote(output)
  end
end
1 Like

Thanks!

I have yet to do a deep dive in macro rules.

I wonder if it would be possible to generate some nicer warning in this case?