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

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

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

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

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

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

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

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

Ответы [ 2 ]

24 голосов
/ 23 июня 2011

Наиболее распространенный подход - это один тестовый модуль на модуль приложения. Если вы правильно называете свои модули, 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

11 голосов
/ 23 июня 2011

Адам дал вам один подход. Другой подход (более распространенный, в моем ограниченном опыте) заключается в размещении модульных тестов в конце каждого модуля, , например . Таким образом вы группируете модуль и его тестовый код вместе в одном файле. Если имена ваших тестовых функций заканчиваются на "_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 тестовых функций. Посмотрите, что работает для вас.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...