2015-10-16 2 views
2

Я начал писать некоторые функции, помогающие проверять утверждения на картах.Eutit утверждает ошибку, сообщающую о неправильном модуле

Скажем, у меня есть следующая карта:

#{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}). 

И I получить следующее сообщение об ошибке:

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 модуля?

ответ

4

Проблема заключается в том, что макросы ?_assert... скомпилированы в модуль asserts, и именно здесь EUnit делает свою магию для определения модулей и номеров строк (во время компиляции, то есть). Если вы замените функцию maps_assert_map_has_updated_values макросом, который вы ввели в заголовочный файл, который вы включили, вы должны увидеть правильную трассировку стека.

+0

Хм. Почему, однако, после того, как строка «в функции утверждает ...» ссылается на «test/asserts.erl, строка 31», нет ли линии «в вызове от», ссылающейся на номер строки в test/map_test.erl? Несомненно, проблема здесь заключается не в том, что модуль утверждений находится в верхней части трассировки стека, но нет ничего после вершины трассировки стека? – Michael

+0

@Michael: В этом случае ваш вызов 'asserts' является последним вызовом в вашей тестовой функции. Erlang выполняет оптимизацию хвостовых вызовов, удаляя этот вызов из стека. Если после этого вы добавите еще одну значительную строку кода, вы сможете увидеть ее в своей трассировке стека. –

+0

Ах, да, конечно, я вижу, хорошее место. – Michael