Philip
Philip

Reputation: 1532

Multiple clauses in EUnit's assertMatch?

I am using Erlang's EUnit for unit testing an application.

I want to assert that a certain test value is between 2 and 3. There's no built-in support for this, so I am trying to use a pair of guards, like this:

myTestCase ->
  ?assertMatch({ok, V} when V>2, V<3,
               unitUnderTest() % expected to return 2.54232...
  ).

This tries to use the guard syntax for andalso.

However, this does not work, presumably because Erlang's parser can't tell the difference between multiple guards and multiple arguments to assertMatch. I tried wrapping various things in parentheses, but haven't found anything that works. On the other hand, when I reduce the expression to just one clause, it succeeds.

Is there a way to express multiple clauses here?

Upvotes: 1

Views: 584

Answers (2)

Pascal
Pascal

Reputation: 14042

You cannot use commas in the syntax, simply because then ?assertMatch is interpreted as a macro with 3 - or more - parameters, and there is no definition for that. But the syntax andalso and orelse works. Why don't you use :

fok() -> {ok,2.7}.

fko() -> {ok,3.7}.

myTestCase(F) ->
    F1 = fun() -> apply(?MODULE,F,[]) end,
    ?assertMatch({ok, V} when V>2 andalso V<3, F1()).

test:

1> c(test).
{ok,test}
2> test:myTestCase(fok).
ok
3> test:myTestCase(fko).
** exception error: {assertMatch,
                        [{module,test},
                         {line,30},
                         {expression,"F1 ( )"},
                         {pattern,"{ ok , V } when V > 2 andalso V < 3"},
                         {value,{ok,3.7}}]}
     in function  test:'-myTestCase/1-fun-1-'/1 (test.erl, line 30)
4>

Upvotes: 1

7stud
7stud

Reputation: 48599

However, this does not work, presumably because Erlang's parser can't tell the difference between multiple guards and multiple arguments to assertMatch

The eunit docs explicitly warn about that:

assertMatch(GuardedPattern, Expr)

GuardedPattern can be anything that you can write on the left hand side of the -> symbol in a case-clause, except that it cannot contain comma-separated guard tests.

How about:

-module(my).
-compile(export_all).
-include_lib("eunit/include/eunit.hrl").

f() ->
    {ok, 3}.


f_test() ->
    ?LET({ok, X}, f(), ?assertMatch( true, X>2 andalso X<4 ) ).

Upvotes: 1

Related Questions