【问题标题】:Eunit assertions error reporting the wrong moduleEunit 断言错误报告错误的模块
【发布时间】:2015-10-16 09:28:59
【问题描述】:

我开始编写一些函数来帮助测试地图上的断言。

假设我有以下地图:

#{a => 0, b => 2}

在我的业务逻辑中调用一个函数后,我希望地图看起来像这样:

#{a => 1, b => 2}

换句话说,我希望

  • 地图在更新后具有相同数量的键
  • a 的值从 0 变为 1
  • b 的值不变

我可以把这个测试留给模式匹配,但是,如果我有一个带有很多键(甚至可能有很多子图)的大地图,问题可能出在哪里并不明显 - 至少需要一些时间是时候找到问题了(也许我期望更新的一些值没有 - 或者可能有一些额外的键等 - 我希望你明白这一点)。

首先,我在我的模块中提出了以下帮助函数:

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

maps_assert_map_has_updated_values(BaseMap, Updates, ResultingMap) ->
    BaseMapKeys = lists:sort(maps:keys(BaseMap)),
    ResultingMapKeys = lists:sort(maps:keys(ResultingMap)),
    UpdatesKeys = lists:sort(maps:keys(Updates)),
    BaseMapWithoutUpdates = maps:without(UpdatesKeys, BaseMap),
    BaseMapKeysWithoutUpdates = lists:sort(maps:keys(BaseMapWithoutUpdates)),
    ResultingMapWithoutUpdates = maps:without(UpdatesKeys, ResultingMap),

    [
     ?_assertEqual(BaseMapKeys, ResultingMapKeys),
     lists:foldl(
       fun(Key, Acc) -> [?_assertEqual({Key, maps:get(Key, Updates)}, 
                       {Key, maps:get(Key, ResultingMap)}) | Acc] end,
       [],
       UpdatesKeys
      ),
     lists:foldl(
       fun(Key, Acc) -> [?_assertEqual({Key, true}, 
                       {Key, maps:is_key(Key, ResultingMap)}) | Acc] end,
       [],
       UpdatesKeys
      ),
     lists:foldl(
       fun(Key, Acc) -> [?_assertEqual({Key, maps:get(Key, BaseMapWithoutUpdates)}, 
                       {Key, maps:get(Key, ResultingMapWithoutUpdates)}) | Acc] end,
       [],
       BaseMapKeysWithoutUpdates
      )
    ].

我从另一个模块调用它,由 eunit 执行:

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

simple_map_test_() ->
    asserts:maps_assert_map_has_updated_values(
        #{a => 0, b => 2}, 
        #{a => 1}, 
        #{a => 1, b => 3}).

我收到以下错误消息:

asserts:30: maps_assert_map_has_updated_values...*failed*    in function asserts:'-maps_assert_map_has_updated_values/3-fun-8-'/3 (test/asserts.erl, line 31)
**error:{assertEqual_failed,[{module,asserts},
                     {line,31},
                     {expression,"{ Key , maps : get ( Key , ResultingMapWithoutUpdates ) }"},
                     {expected,{b,2}},
                     {value,{b,3}}]}

几乎是我想要的,因为它报告了地图中有问题的键和有问题的值,然而它报告了asserts模块中的错误,即使我有兴趣查看失败的实际测试,而不是对断言模块的引用。我认为测试生成器正好可以解决这个问题,但我无法让它以这种方式工作。

有什么方法可以让eunit 报告实际的测试模块(map_tests,函数/测试simple_map_test X 行)而不是我的asserts 模块?

【问题讨论】:

    标签: erlang eunit


    【解决方案1】:

    问题是,?_assert... 宏被编译到 asserts 模块中,这就是 EUnit 发挥魔力来计算模块和行号的地方(即在编译时)。如果您将 maps_assert_map_has_updated_values 函数替换为放入包含在头文件中的宏,您应该会看到正确的堆栈跟踪。

    【讨论】:

    • 嗯。但是,为什么在引用“test/asserts.erl,第 31 行”的“in function asserts...”行之后没有引用 test/map_test.erl 中行号的“in call from”行?这里的问题肯定不是 asserts 模块在堆栈跟踪的顶部,而是堆栈跟踪的顶部之后什么都没有?
    • @Michael:在这种情况下,您对asserts 的调用是测试用例函数中的最后一次调用。 Erlang 进行尾调用优化,从堆栈中删除该调用。如果您在该调用之后添加另一行重要的代码,您应该能够在堆栈跟踪中看到它。
    猜你喜欢
    • 1970-01-01
    • 2011-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-21
    • 2013-01-03
    • 1970-01-01
    相关资源
    最近更新 更多