ExUnit without assert/refute, relying solely on pattern matching?
Asked Answered
F

2

11

I'm testing the return value of a function. Which of the two is the preferred way?

test "extra verbose, using assert" do
  {:error, reason} = MyModule.my_fun
  assert reason == :nope
end

test "using pattern matching only" do
  {:error, :nope} = MyModule.my_fun
end

I like the first one because, I don't now, a test needs an assert statement and the error message when running the test is more descriptive. Otoh, a MatchError with line number should also be enough.

Freehearted answered 12/4, 2017 at 8:29 Comment(0)
S
22

You can use assert with = to get both an assert and a more descriptive error message, and with just one line of code:

assert {:error, :nope} = MyModule.my_fun

Unlike with ==, you can use any pattern on the LHS, although in this case, = can be replaced with == since the LHS is both a valid pattern and value.

On failure, you'll get an error message that's better than just doing the pattern matching without the assert, e.g.

  1) test the truth (MTest)
     test/m_test.exs:10
     match (=) failed
     code:  {:error, :nope} = MyModule.my_fun()
     right: {:error, :nop}
     stacktrace:
       test/m_test.exs:11: (test)
Seeley answered 12/4, 2017 at 8:34 Comment(5)
For me the main drawback to using assert on a match is you won't get the left vs right comparison in the test resultsTorey
Is assert {:error, :nope} = MyModule.my_fun really testing anything? If the pattern matches, it will basically assert that the tuple {:error, :nope} is truthy, no? If the pattern doesn't match, there's still the MatchError.Freehearted
@carp nope, there will not be any MatchError. assert handles = specially. I added an example test failure output to the answer just now.Seeley
@Torey yes, if the LHS is a valid value, I'd use == to get that nice colored diff, but if it's not a valid value, this is better than doing just pattern = value in the test.Seeley
@Seeley very true, I guess when asserting atom results the == isn't really necessary. Bottom line is always use an assert :)Torey
S
1

Whoever comes around this in 2022: consider always using assert, even in conjunction of pattern matching, e.g.:

assert {:error, :nope} = MyModule.my_fun()

Since 1.10, Elixir supports rendering colored diff when pattern matching fails: https://github.com/elixir-lang/elixir/commit/98c6bba436cc4833363295e5fedd3f819504d79d

Shapely answered 5/11, 2022 at 17:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.