1

我想编写测试,其中设置和清理功能不会为每个测试执行一次,而是一次 - 在测试开始和测试结束时。

所以我尝试了这种方式:

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

示例 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(!) 个测试。

我可以忘记块语句并编写没有变量的测试,但我认为这可能很难阅读,它应该与块一起使用。

4

1 回答 1

3

文档说:

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

一个空函数值(即,一个接受零参数的乐趣)。例子:

   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

模块名称:功能名称/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*)。我希望现在很清楚。

于 2013-04-26T06:14:05.877 回答