Erlang - функция настройки Eunit не работает

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

Итак, я попробовал так:

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).

or

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: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(!)

Я мог бы просто забыть оператор блока и писать тесты без переменных, но я думаю, что это было бы ужасно читать, и это должно работать с блоками.


person otisonoza    schedule 25.04.2013    source источник


Ответы (1)


В документации говорится:

Простой тестовый объект может быть одним из следующих:

Нульарное функциональное значение (т. е. забава, не принимающая аргументов). Примеры:

   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*). Надеюсь теперь понятно.

person Wacław Borowiec    schedule 26.04.2013
comment
Установка работает с вашим решением, но тесты просто не запускаются. При запуске eunit запускается генератор_тест_/0, но запись любого макроса ?_assert в файле some_test1/0 не приводит к изменениям. Запустив подробный режим, я не вижу тестов ?_assert, и, например, запись ?_assertEqual(3, 4) проходит. - person otisonoza; 26.04.2013
comment
Написать ?assertEqual(3, 4) не получается, но eunit считает это одним тестом, но есть 2 утверждения. - person otisonoza; 26.04.2013
comment
Внутри теста вы должны использовать только макросы ?assert*, а не ?_assert*. Приведите проблемный код, пожалуйста. - person Wacław Borowiec; 26.04.2013
comment
Пример добавлен. Спасибо за помощь. - person otisonoza; 26.04.2013