Erlang - Eunit设置功能无法运行

时间:2013-04-25 19:31:14

标签: unit-testing testing erlang assertions eunit

我想编写测试,其中setup和cleanup函数不会针对每个测试执行,而是一次 - 在测试开始时和测试结束时执行。

所以我试着这样:

generator_test_() ->
{setup, fun setup/0, fun cleanup/1,
    {inorder,
        [
            some_test1()
            %...
        ]
    }
}.

some_test1/0

的位置
some_test1() ->
    begin
        Value1 = something1(),
        Value2 = something2(),
        [?_assertEqual(Value1, Value2)]
    end.

安装程序不会以这种方式执行。

但是这样:

some_test1() ->
    ?_test(begin
        Value1 = something1(),
        Value2 = something2(),
        [?_assertEqual(Value1, Value2)]
    end).

some_test1() ->
    [?_assertEqual(something1(), something2())].

一切都很好。

我不明白为什么它有效,我的问题是我不能写多个断言?_test(....)。

some_test1() ->
    ?_test(begin
        Value1 = something1(),
        Value2 = something2(),
        [?_assertEqual(Value1, Value2),
        ?_assertEqual(Value1, Value2)]
    end).

通过运行eunit:test(my_module, [verbose]).,我发现只有1个测试通过。

更新

示例1

一个小例子:

-module(example).

-include_lib("eunit/include/eunit.hrl").

generator_test_() ->
    {setup, fun setup/0, fun cleanup/1,
        {inorder,
            fun() -> some_test1() end
        }
    }.

some_test1() ->
    begin
        X = 3,
        Y = 4,
        %%% This is a test set/deep list as it
        %%% contains two tests.
        [?_assertEqual(X, Y),
        ?_assertEqual(ok, ok)]
    end.

setup() ->
    erlang:display("---SETUP CALLED---"),
    "setup".

cleanup(_) ->
    ok.

运行eunit:

eunit:test(example, [verbose]).
======================== EUnit ========================
"---SETUP CALLED---"
module 'example'
  example: generator_test_...ok
  [done in 0.004 s]
=======================================================
  Test passed.
ok

一个小修改:

some_test1() ->
    begin
        X = 3,
        Y = 4,
        %%% This is a test set/deep list as it
        %%% containst two tests.
        [?_assertEqual(X, Y),
        ?_assertEqual(it_doesnt_work, ok)]
    end.

测试仍然通过。

例2

然而

some_test1() ->
    begin
        X = 3,
        Y = 4,
        %%% These are just two simple tests
        ?assertEqual(X, Y),
        ?assertEqual(it_doesnt_work, ok)
    end.

失败

eunit:test(example, [verbose]).
======================== EUnit ========================
"---SETUP CALLED---"
module 'example'
  example: generator_test_...*failed*
in function example:'-some_test1/0-fun-0-'/1 (example.erl, line 17)
in call from example:some_test1/0 (example.erl, line 17)
**error:{assertEqual_failed,[{module,example},
                     {line,17},
                     {expression,"Y"},
                     {expected,3},
                     {value,4}]}


  [done in 0.003 s]
=======================================================
  Failed: 1.  Skipped: 0.  Passed: 0.
error

BUT

示例3

generator_test_() ->
    {setup, fun setup/0, fun cleanup/1,
        {inorder,
            some_test1()
        }
    }.

some_test1() ->
    [?_assertEqual(3, 3),
    ?_assertEqual(ok, ok)].

eunit:test(example, [verbose]).
======================== EUnit ========================
"---SETUP CALLED---"
module 'example'
  example:13: some_test1...ok
  example:14: some_test1...ok
  [done in 0.005 s]
=======================================================
  All 2 tests passed.
ok

现在我看到有2个(!)测试。

我可以忘记块语句并在没有变量的情况下编写测试,但我认为阅读起来可能很糟糕,而且应该可以使用块。

1 个答案:

答案 0 :(得分:3)

documentation说:

  

一个简单的测试对象是以下之一:

     

一个无效的功能值(即一个零参数的乐趣)。例子:

   fun () -> ... end
   fun some_function/0
   fun some_module:some_function/0

A tuple {test, ModuleName, FunctionName}, where ModuleName and FunctionName are atoms, referring to the function
     

模块名:FunctionName / 0

A pair {LineNumber, SimpleTest}, where LineNumber is a nonnegative integer and SimpleTest is another simple test object. LineNumber
     

应指明测试的源代码行。像这样的对   通常只通过?_test(...)宏创建;请参阅基本宏。

所以你可以指定你的测试,例如:

generator_test_() ->
{setup, fun setup/0, fun cleanup/1,
    {inorder,
        [
            fun() -> some_test1() end
            %% OR
            fun some_test1/0
        ]
    }
}.

此外:

  

(请注意,这些宏也有相应的形式,以...开头   一个“_”(下划线)字符,如?_assert(BoolExpr),它创建一个   “测试对象”而不是立即执行测试。这是   相当于写?_test(断言(BoolExpr))等等。)

这就是你的?_ *测试生成器工作的原因。

修改

示例2和3是做事的好方法。示例2将简单的测试乐趣放入测试列表中。示例3生成了2个测试的列表,因为

[?_assertEqual(a, b), ?_assertEqual(a == a)]

实际上已扩展为

[fun() -> ?assertEqual(a, b) end, fun() -> ?assertEqual(a, a) end]

如果需要变量,请使用示例2,否则使用示例3。示例1没有给出预期的结果,因为“fun() - > some_test1()end”是一个测试本身,它应该执行真正的断言(?assert *)而不是产生另一个测试(?_assert *)。我希望现在很清楚。