【问题标题】:Erlang - Eunit setup function doesn't runErlang - Eunit 设置功能不运行
【发布时间】:2023-03-25 11:55:02
【问题描述】:

我想编写测试,其中 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

但是

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

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

【问题讨论】:

    标签: unit-testing testing erlang assertions eunit


    【解决方案1】:

    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
    

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

    【讨论】:

    • 安装程序确实与您的解决方案一起运行,但测试只是不运行。通过运行 eunit,generator_test_/0 运行,但在 some_test1/0 中编写任何 ?_assert 宏都不会产生任何变化。通过运行详细模式,我看不到 ?_assert 测试,例如编写 ?_assertEqual(3, 4) 通过。
    • 写入 ?assertEqual(3, 4) 失败,但 eunit 将其视为一个测试,但有 2 个断言。
    • 在测试中你应该只使用 ?assert* 宏,而不是 ?_assert* 宏。请提供有问题的代码。
    • 添加了示例。感谢您的帮助。
    猜你喜欢
    • 2012-05-05
    • 2023-03-26
    • 2017-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-02
    • 1970-01-01
    • 2018-06-21
    相关资源
    最近更新 更多