Подтвердить что ты не робот

Лучшие практики/соглашения для написания модульных тестов Erlang с использованием eunit

В настоящее время я изучаю Erlang и размышлял о том, какие хорошие практики или соглашения для модульного тестирования? В настоящее время я использую eunit.

Чтобы задать этот вопрос:

  • В настоящее время я пишу один модуль unit test для каждой функции, так что мои тестовые имена довольно прямолинейны и принимают форму should_do_desired_behaviour_test().

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

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

Итак, я думаю, я не совсем уверен, какой подход принять, или если я даже дистанционно на правильном пути с этим. Как вы обычно управляете модульными тестами?

Приветствия.

4b9b3361

Ответ 1

Самым распространенным подходом является один тестовый модуль для каждого модуля приложения. Если вы правильно назовете свои модули, EUnit найдет и проведет все ваши тесты для вас, не нужно создавать глобальный модуль, который запускает тесты. Например, данный:

  • SRC/
    • meck.erl
    • meck_mod.erl
  • тест /
    • meck_tests.erl
    • meck_mod_tests.erl

Если вы запустите eunit:test(meck), он обнаружит (если на вашем пути) модуль meck_tests и запустит meck_tests:test(). Функция test() автоматически вставляется в модуль через EUnit, когда вы включаете eunit.hrl.

Что касается соглашений об именах, я обычно заканчиваю чем-то следующим образом:

-module(my_tests).

-export([functiona_should_do_this/0]).
-export([functionb_should_do_that/0]).
-export([functionb_should_not_crash/0]).
% etc

Если вам нужны хорошие имена, которые появляются в тестовых прогонах, используйте возможности тестового генератора EUnit:

all_my_test_() ->
    [{"Should not break X",  fun first_test/0},
     {"Should perform Y", fun other_test/0}].

Любая функция, заканчивающаяся на test_, сообщает EUnit, что она должна возвращать список тестов (это называется тестовым генератором). Список тестов может состоять только из списка забав, списка кортежей, где первый элемент представляет собой строковое описание теста или более сложную настройку:

advanced_test_() ->
    {foreach, fun setup/0, fun teardown/1,
     [{"Assert X", fun test1/0}]}.

Это будет выполняться setup/0 перед каждым тестовым случаем и teardown/1 после каждого тестового примера. Аргументом для teardown/1 является возвращаемое значение из setup/0. Вы можете назвать эти функции чем угодно.

Имеется обширная документация о том, как использовать EUnit здесь.

Вот как выглядит мой тестовый модуль: https://github.com/eproxus/meck/blob/master/test/meck_tests.erl

Ответ 2

Адам дал вам один подход. Другой подход (более общий, в моем ограниченном опыте) заключается в том, чтобы поместить модульные тесты в конце каждого модуля, как это. Таким образом, вы группируете модуль и вместе проверяете код в том же файле. Если имена ваших тестовых функций заканчиваются на "_test", EUnit автоматически распознает их при вызове eunit: test (module) или module: test() (вам не нужно писать функцию module: test() самостоятельно, EUnit экспортирует его для вас).

Как и для нескольких тестовых функций: вы не делаете этого, если не хотите. Вы можете просто складывать все тестовые примеры в одну и ту же функцию, если вам это нравится, например:

whatever_test() ->
    234 = foo(bar),
    345 = foo(baz),
    [...]
    foobar = quux(baz).

И что это. Некоторым людям нравится ставить тест evey в свою собственную функцию, некоторые складывают его только в одну функцию. Я обычно группирую подобные тесты в одной функции и заканчиваю 3-4-5 тестовыми функциями. Посмотрите, что работает для вас.

Что касается "глобального тестового модуля", снова Адам дал вам хороший совет. И снова есть еще один вариант: rebar. Это инструмент, который помогает вам тестировать приложения erlang (и многое другое). См. Здесь для руководства: http://vimeo.com/8311407 Арматура просто автоматически определит ваши тестовые функции внутри модулей и запустит их для вас.