Вопрос немного расплывчатый («Эрланг параллелен, проверь его с Эрлангом!»), Но я попытаюсь уточнить.
Тестирование кода Erlang может варьироваться от простого простого (правильный ввод дает правильный вывод) до настройки сложных тестовых привязок, которые проверяют, что ваш компонент ведет себя так, как должен. То, что лучше всего подходит для вашей конкретной ситуации, полностью зависит от ваших требований и количества испытаний черного ящика / белого ящика, которые вы хотите провести.
Частью красоты Erlang является способность сделать параллелизм прозрачным. Рассмотрим следующий пример (функция, которая распараллеливает суммирование списка списков):
deep_sum(ListOfLists) ->
Parent = self(),
[spawn(fun() -> Parent ! lists:sum(List) end) || List <- ListOfLists],
lists:sum([receive Sum -> Sum end || _ <- ListOfLists]).
Обычно вы тестируете это с помощью очень простого теста EUnit:
deep_sum_test() ->
?assertEqual(0, deep_sum([0, 0, 0, 0])),
?assertEqual(40, deep_sum([10, 10, 10, 10]).
Теперь, скажем, у нас есть немного более явный API для этой функциональности: пул процессов в качестве аргумента:
deep_sum(Pool, ListOfLists) ->
distribute_lists(Pool, ListOfLists),
lists:sum([receive Sum -> Sum end || _ <- ListOfLists]).
distribute_lists(Pool, ListOfLists) -> distribute_lists(Pool, Pool, ListOfLists).
distribute_lists([P|Pool], All, [L|ListOfLists]) ->
P ! {self(), L},
distribute_lists(Pool, All, ListOfLists);
distribute_lists([], All, ListOfLists) ->
distribute_lists(All, All, ListOfLists);
distribute_lists(_Pool, _All, []) ->
ok.
При тестировании мы имеем дело с подделкой этого пула процессов:
deep_sum_test() ->
Pool = [spawn_link(fun() -> fake_pool(1) end) || _ <- lists:seq(1, 3)],
?assertEqual(4, deep_sum(Pool, [lists:seq(1, 3) || _ <- list:seq(1, 4)]),
?assertEqual(7, deep_sum(Pool, [lists:seq(1, 3) || _ <- list:seq(1, 7)]),
[P ! stop || P <- Pool].
fake_pool(CannedResponse) ->
receive
{From, _L} -> From ! CannedResponse;
stop -> ok
end,
fake_pool(CannedResponse).
Как видите, тестирование параллельных программ в Erlang может принимать различные формы. Это очень простые примеры, но с помощью встроенных в Erlang примитивов параллелизма очень легко создать нужный тип тестового набора, абстрагируясь на нужных уровнях.
Я обычно нахожу TDD ортогональным к тому, когда вы тестируете параллельный код или нет, поэтому указанные методы тестирования могут быть использованы и для обычного модульного тестирования.