Pytanie jest nieco niejasne ("Erlang jest równoczesny, przetestuj go z Erlangiem!"), Ale postaram się trochę rozwinąć.
Testowanie kodu Erlang może się wahać od prostego prostego (prawe wejście tworzy właściwe wyjście) do konfigurowania złożonych wiązek testowych, które sprawdzają, czy komponent zachowuje się tak, jak powinien. To, co jest najlepsze w danej sytuacji, zależy całkowicie od wymagań, które posiadasz, oraz od ilości testów czarnych skrzynek/białych skrzynek, które chcesz wykonać.
Częścią piękna Erlanga jest możliwość przejrzystego współbieżności.Rozważmy następujący przykład (funkcję parallelizes zbiorcze listy list):
deep_sum(ListOfLists) ->
Parent = self(),
[spawn(fun() -> Parent ! lists:sum(List) end) || List <- ListOfLists],
lists:sum([receive Sum -> Sum end || _ <- ListOfLists]).
Będziesz zwykle przetestować to z bardzo prostego testu EUnit:
deep_sum_test() ->
?assertEqual(0, deep_sum([0, 0, 0, 0])),
?assertEqual(40, deep_sum([10, 10, 10, 10]).
Teraz, powiedzmy, że mają nieco bardziej wyraźny API do tego funkcjonalność: basen proces jako argumentu:
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.
testując to mamy do czynienia z fałszowanie tej puli procesów:
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).
Jak widać, testowanie programów współbieżnych w Erlang może przybierać różne kształty. Są to bardzo proste przykłady, ale dzięki wbudowanym prymitywom współbieżnym Erlanga bardzo łatwo jest stworzyć rodzaj uprzęży testowej, którą chcesz, i abstrakty na właściwych poziomach.
Zwykle stwierdzam, że TDD jest ortogonalny, aby testować kod współbieżny, a więc te techniki testowania mogą być również używane do normalnych testów jednostkowych.
Ta rada odnosi się do języka takiego jak Java z współdzieloną współbieżnością stanu. Jednak Erlang używa przekazywania komunikatów i masz kontrolę nad tym, kiedy dane są wysyłane do innych procesów iw jakiej kolejności są odbierane. Zasadniczo więcej kontroli. Wydaje się, że powinny istnieć kod/wzorce testowe. – madlep
To prawda, że brak współdzielonego stanu pozwala uniknąć problemów związanych z uszkodzeniem danych lub niespójnością. Ale nadal musisz martwić się synchronizacją. Mam rację? –