質問は少しあいまいですが (「Erlang は並行処理です。Erlang でテストしてください!」)、少し詳しく説明します。
Erlang コードのテストは、単純なもの (正しい入力が正しい出力を生成する) から、コンポーネントが本来の動作をすることを検証する複雑なテスト ハーネスのセットアップまで、さまざまです。与えられた状況に最適なものは、あなたが持っている要件と、実行したいブラックボックス/ホワイトボックステストの量に完全に依存します.
Erlang の優れた点の 1 つは、同時実行を透過的にできることです。次の例 (リストのリストの合計を並列化する関数) を考えてみましょう。
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 は並行コードをテストしているかどうかに関係なく直交していると考えているため、上記のテスト手法は通常の単体テストにも使用できます。