在 erlang eunit failure 中打印测试夹具描述
Print test fixture description in erlang eunit failure
有没有办法打印使用fixtures的erlang测试生成器的测试描述?使用生成器很难判断哪个测试实际上失败了,打印描述会有所帮助。
示例:
-module(math_test).
-include_lib("eunit/include/eunit.hrl").
-define(test(Desc, F), {Desc, {setup, fun setup/0, fun cleanup/1, F}}).
setup() ->
ok.
cleanup(_) ->
ok.
math_test_ () ->
[
?test("adds two numbers", fun add_two_numbers/0),
?test("subtract two numbers", fun subtract_two_numbers/0),
?test("undefined method called", fun undefined_error/0)
].
add_two_numbers () ->
?assertEqual(2, 1 + 3).
subtract_two_numbers () ->
?assertEqual(1, 2 - 2).
undefined_error () ->
undefined_module:uh_oh().
然后运行它
[root@a7c901c022bb src]# rebar3 eunit --module=math_test
===> Verifying dependencies...
===> Compiling math
===> Performing EUnit tests...
FFF
Failures:
1) math_test:math_test_/0
Failure/Error: ?assertEqual(2, 1 + 3)
expected: 2
got: 4
%% /src/_build/test/lib/math/src/math_test.erl:20:in `math_test:-add_two_numbers/0-fun-0-/1`
Output:
Output:
2) math_test:math_test_/0
Failure/Error: ?assertEqual(1, 2 - 2)
expected: 1
got: 0
%% /src/_build/test/lib/math/src/math_test.erl:23:in `math_test:-subtract_two_numbers/0-fun-0-/1`
Output:
Output:
3) math_test:math_test_/0
Failure/Error: {error,undef,[{undefined_module,uh_oh,[],[]}]}
Output:
前 2 个错误没问题,但不是很好 -- 您至少可以在断言中看到实际出错的地方。
然而,第三个错误(调用未定义 module/method)是非常错误的地方——没有真正的方法来判断它来自哪里!
有没有办法改进,比如打印测试描述和失败日志?
您可以做的一件事是将测试描述放在测试本身上,而不是整个 setup
元组。即,更改此行:
-define(test(Desc, F), {Desc, {setup, fun setup/0, fun cleanup/1, F}}).
至:
-define(test(Desc, F), {setup, fun setup/0, fun cleanup/1, {Desc, F}}).
进行该更改后,将打印测试说明:
Failures:
1) math_test:math_test_/0: adds two numbers
Failure/Error: ?assertEqual(2, 1 + 3)
expected: 2
got: 4
%% /tmp/math_test/mylib/_build/test/lib/mylib/test/math_test.erl:20:in `math_test:-add_two_numbers/0-fun-0-/0`
Output:
Output:
2) math_test:math_test_/0: subtract two numbers
Failure/Error: ?assertEqual(1, 2 - 2)
expected: 1
got: 0
%% /tmp/math_test/mylib/_build/test/lib/mylib/test/math_test.erl:23:in `math_test:-subtract_two_numbers/0-fun-0-/0`
Output:
Output:
3) math_test:math_test_/0: undefined method called
Failure/Error: {error,undef,[{undefined_module,uh_oh,[],[]}]}
Output:
另一件事是用 ?_test
宏而不是简单的 fun
术语指定测试函数:
math_test_ () ->
[
?test("adds two numbers", ?_test(add_two_numbers())),
?test("subtract two numbers", ?_test(subtract_two_numbers())),
?test("undefined method called", ?_test(undefined_error()))
].
?_test
宏会记住它出现的行号,并在测试失败时将其包含在输出中:
1) math_test:math_test_/0:14: adds two numbers
[...]
2) math_test:math_test_/0:15: subtract two numbers
[...]
3) math_test:math_test_/0:16: undefined method called
[...]
现在您可以知道从哪一行调用了这些测试。
另一种方法是使用单独的函数 return eunit "test objects" 而不仅仅是 运行 测试。这将涉及使用 ?_assertEqual
而不是 ?assertEqual
,或者将整个内容包装在 ?_test
:
中
math_test_ () ->
[
?test("adds two numbers", add_two_numbers()),
?test("subtract two numbers", subtract_two_numbers()),
?test("undefined method called", undefined_error())
].
add_two_numbers () ->
?_assertEqual(2, 1 + 3).
subtract_two_numbers () ->
?_assertEqual(1, 2 - 2).
undefined_error () ->
?_test(undefined_module:uh_oh())
然后输出包含行号和各个测试函数的名称:
Failures:
1) math_test:add_two_numbers/0:20: adds two numbers
Failure/Error: ?assertEqual(2, 1 + 3)
expected: 2
got: 4
%% /tmp/math_test/mylib/_build/test/lib/mylib/test/math_test.erl:20:in `math_test:-add_two_numbers/0-fun-0-/0`
Output:
Output:
2) math_test:subtract_two_numbers/0:23: subtract two numbers
Failure/Error: ?assertEqual(1, 2 - 2)
expected: 1
got: 0
%% /tmp/math_test/mylib/_build/test/lib/mylib/test/math_test.erl:23:in `math_test:-subtract_two_numbers/0-fun-0-/0`
Output:
Output:
3) math_test:undefined_error/0:26: undefined method called
Failure/Error: {error,undef,[{undefined_module,uh_oh,[],[]}]}
Output:
@legoscia 的回答很好,但我也怀疑 rebar3 实现的错误报告对于此类错误不是最佳的。 运行 直接来自 eunit 的测试及其默认输出,你得到这个:
2> eunit:test(math_test).
math_test: math_test_...*failed*
in function math_test:'-add_two_numbers/0-fun-0-'/0 (math_test.erl, line 22)
**error:{assertEqual,[{module,math_test},
{line,22},
{expression,"1 + 3"},
{expected,2},
{value,4}]}
output:<<"">>
math_test: math_test_...*failed*
in function math_test:'-subtract_two_numbers/0-fun-0-'/0 (math_test.erl, line 25)
**error:{assertEqual,[{module,math_test},
{line,25},
{expression,"2 - 2"},
{expected,1},
{value,0}]}
output:<<"">>
math_test: math_test_...*failed*
in function undefined_module:uh_oh/0
called as uh_oh()
**error:undef
output:<<"">>
=======================================================
Failed: 3. Skipped: 0. Passed: 0.
使用'verbose'选项,它还会在每次设置前打印描述。此外,将描述移动到测试乐趣,并使用 ?_test(...) 宏创建比普通乐趣具有更多位置信息的测试乐趣,如@legoscia 建议的那样,您将得到以下输出:
math_test:18: math_test_ (undefined method called)...*failed*
in function undefined_module:uh_oh/0
called as uh_oh()
**error:undef
output:<<"">>
您可以将此报告给 rebar3 维护者。
有没有办法打印使用fixtures的erlang测试生成器的测试描述?使用生成器很难判断哪个测试实际上失败了,打印描述会有所帮助。
示例:
-module(math_test).
-include_lib("eunit/include/eunit.hrl").
-define(test(Desc, F), {Desc, {setup, fun setup/0, fun cleanup/1, F}}).
setup() ->
ok.
cleanup(_) ->
ok.
math_test_ () ->
[
?test("adds two numbers", fun add_two_numbers/0),
?test("subtract two numbers", fun subtract_two_numbers/0),
?test("undefined method called", fun undefined_error/0)
].
add_two_numbers () ->
?assertEqual(2, 1 + 3).
subtract_two_numbers () ->
?assertEqual(1, 2 - 2).
undefined_error () ->
undefined_module:uh_oh().
然后运行它
[root@a7c901c022bb src]# rebar3 eunit --module=math_test
===> Verifying dependencies...
===> Compiling math
===> Performing EUnit tests...
FFF
Failures:
1) math_test:math_test_/0
Failure/Error: ?assertEqual(2, 1 + 3)
expected: 2
got: 4
%% /src/_build/test/lib/math/src/math_test.erl:20:in `math_test:-add_two_numbers/0-fun-0-/1`
Output:
Output:
2) math_test:math_test_/0
Failure/Error: ?assertEqual(1, 2 - 2)
expected: 1
got: 0
%% /src/_build/test/lib/math/src/math_test.erl:23:in `math_test:-subtract_two_numbers/0-fun-0-/1`
Output:
Output:
3) math_test:math_test_/0
Failure/Error: {error,undef,[{undefined_module,uh_oh,[],[]}]}
Output:
前 2 个错误没问题,但不是很好 -- 您至少可以在断言中看到实际出错的地方。
然而,第三个错误(调用未定义 module/method)是非常错误的地方——没有真正的方法来判断它来自哪里!
有没有办法改进,比如打印测试描述和失败日志?
您可以做的一件事是将测试描述放在测试本身上,而不是整个 setup
元组。即,更改此行:
-define(test(Desc, F), {Desc, {setup, fun setup/0, fun cleanup/1, F}}).
至:
-define(test(Desc, F), {setup, fun setup/0, fun cleanup/1, {Desc, F}}).
进行该更改后,将打印测试说明:
Failures:
1) math_test:math_test_/0: adds two numbers
Failure/Error: ?assertEqual(2, 1 + 3)
expected: 2
got: 4
%% /tmp/math_test/mylib/_build/test/lib/mylib/test/math_test.erl:20:in `math_test:-add_two_numbers/0-fun-0-/0`
Output:
Output:
2) math_test:math_test_/0: subtract two numbers
Failure/Error: ?assertEqual(1, 2 - 2)
expected: 1
got: 0
%% /tmp/math_test/mylib/_build/test/lib/mylib/test/math_test.erl:23:in `math_test:-subtract_two_numbers/0-fun-0-/0`
Output:
Output:
3) math_test:math_test_/0: undefined method called
Failure/Error: {error,undef,[{undefined_module,uh_oh,[],[]}]}
Output:
另一件事是用 ?_test
宏而不是简单的 fun
术语指定测试函数:
math_test_ () ->
[
?test("adds two numbers", ?_test(add_two_numbers())),
?test("subtract two numbers", ?_test(subtract_two_numbers())),
?test("undefined method called", ?_test(undefined_error()))
].
?_test
宏会记住它出现的行号,并在测试失败时将其包含在输出中:
1) math_test:math_test_/0:14: adds two numbers
[...]
2) math_test:math_test_/0:15: subtract two numbers
[...]
3) math_test:math_test_/0:16: undefined method called
[...]
现在您可以知道从哪一行调用了这些测试。
另一种方法是使用单独的函数 return eunit "test objects" 而不仅仅是 运行 测试。这将涉及使用 ?_assertEqual
而不是 ?assertEqual
,或者将整个内容包装在 ?_test
:
math_test_ () ->
[
?test("adds two numbers", add_two_numbers()),
?test("subtract two numbers", subtract_two_numbers()),
?test("undefined method called", undefined_error())
].
add_two_numbers () ->
?_assertEqual(2, 1 + 3).
subtract_two_numbers () ->
?_assertEqual(1, 2 - 2).
undefined_error () ->
?_test(undefined_module:uh_oh())
然后输出包含行号和各个测试函数的名称:
Failures:
1) math_test:add_two_numbers/0:20: adds two numbers
Failure/Error: ?assertEqual(2, 1 + 3)
expected: 2
got: 4
%% /tmp/math_test/mylib/_build/test/lib/mylib/test/math_test.erl:20:in `math_test:-add_two_numbers/0-fun-0-/0`
Output:
Output:
2) math_test:subtract_two_numbers/0:23: subtract two numbers
Failure/Error: ?assertEqual(1, 2 - 2)
expected: 1
got: 0
%% /tmp/math_test/mylib/_build/test/lib/mylib/test/math_test.erl:23:in `math_test:-subtract_two_numbers/0-fun-0-/0`
Output:
Output:
3) math_test:undefined_error/0:26: undefined method called
Failure/Error: {error,undef,[{undefined_module,uh_oh,[],[]}]}
Output:
@legoscia 的回答很好,但我也怀疑 rebar3 实现的错误报告对于此类错误不是最佳的。 运行 直接来自 eunit 的测试及其默认输出,你得到这个:
2> eunit:test(math_test).
math_test: math_test_...*failed*
in function math_test:'-add_two_numbers/0-fun-0-'/0 (math_test.erl, line 22)
**error:{assertEqual,[{module,math_test},
{line,22},
{expression,"1 + 3"},
{expected,2},
{value,4}]}
output:<<"">>
math_test: math_test_...*failed*
in function math_test:'-subtract_two_numbers/0-fun-0-'/0 (math_test.erl, line 25)
**error:{assertEqual,[{module,math_test},
{line,25},
{expression,"2 - 2"},
{expected,1},
{value,0}]}
output:<<"">>
math_test: math_test_...*failed*
in function undefined_module:uh_oh/0
called as uh_oh()
**error:undef
output:<<"">>
=======================================================
Failed: 3. Skipped: 0. Passed: 0.
使用'verbose'选项,它还会在每次设置前打印描述。此外,将描述移动到测试乐趣,并使用 ?_test(...) 宏创建比普通乐趣具有更多位置信息的测试乐趣,如@legoscia 建议的那样,您将得到以下输出:
math_test:18: math_test_ (undefined method called)...*failed*
in function undefined_module:uh_oh/0
called as uh_oh()
**error:undef
output:<<"">>
您可以将此报告给 rebar3 维护者。