eunit:如何测试一个简单的过程?

jaw*_*jaw 5 testing erlang process eunit

我正在编写一个模块的测试,该模块在一个简单的过程中运行spawn_link(?MODULE, init, [self()]).

在我的eunit测试中,我定义了一个设置和拆卸功能以及一组测试生成器.

all_tests_test_() ->
    {inorder, {
        foreach,
        fun setup/0,
        fun teardown/1,
        [
            fun my_test/1
        ]}
    }.
Run Code Online (Sandbox Code Playgroud)

设置乐趣创建了测试过程:

setup() ->
    {ok, Pid} = protocol:start_link(),
    process_flag(trap_exit,true),
    error_logger:info_msg("[~p] Setting up process ~p~n", [self(), Pid]),
    Pid.
Run Code Online (Sandbox Code Playgroud)

测试看起来像这样:

my_test(Pid) ->
    [ fun() ->
            error_logger:info_msg("[~p] Sending to ~p~n", [self(), Pid]),
            Pid ! something,
            receive
                Msg -> ?assertMatch(expected_result, Msg)
            after
                500 -> ?assert(false)
            end
        end ].
Run Code Online (Sandbox Code Playgroud)

我的大多数模块都是gen_server但是为此我认为没有所有gen_server样板代码会更容易...

测试的输出如下所示:

=INFO REPORT==== 31-Mar-2014::21:20:12 ===
[<0.117.0>] Setting up process <0.122.0>

=INFO REPORT==== 31-Mar-2014::21:20:12 ===
[<0.124.0>] Sending to <0.122.0>

=INFO REPORT==== 31-Mar-2014::21:20:12 ===
[<0.122.0>] Sending expected_result to <0.117.0>
protocol_test: my_test...*failed*
in function protocol_test:'-my_test/1-fun-0-'/0 (test/protocol_test.erl, line 37)
**error:{assertion_failed,[{module,protocol_test},
                   {line,37},
                   {expression,"false"},
                   {expected,true},
                   {value,false}]}
Run Code Online (Sandbox Code Playgroud)

从Pids中可以看出,正在运行的任何进程setup(117)与运行测试用例(124)的进程不同.然而,测试过程是相同的(122).这导致测试用例失败,因为接收永远不会收到消息并且会进入超时.

这是eunit为了运行测试用例而产生新进程的预期行为吗?

通常,有没有更好的方法来测试进程或其他异步行为(如强制转换)?或者你会建议总是使用gen_server来建立同步接口吗?

谢谢!

[编辑]

为了澄清协议如何知道这个过程,这很start_link/0有趣:

start_link() ->
    Pid = spawn_link(?MODULE, init, [self()]),
    {ok, Pid}.
Run Code Online (Sandbox Code Playgroud)

该协议与呼叫者紧密相关.如果他们中的任何一个崩溃,我希望另一个人也死了.我知道我可以使用gen_server和supervisor,实际上它是在应用程序的某些部分中做到的,但对于这个模块,我认为它有点超过顶部.

Pas*_*cal 5

你试过了吗:

all_tests_test_() ->
    {inorder, {
        foreach,
        local,
        fun setup/0,
        fun teardown/1,
        [
            fun my_test/1
        ]}
    }.
Run Code Online (Sandbox Code Playgroud)

从文档来看,这似乎就是您所需要的。

  • `local` 成功了。我很长一段时间都忽略了“Where”部分;)实际上,我有一种感觉,与其他语言和测试套件相比,我在修复 eunit 测试用例上花费了更多的时间,而不是实现代码。eunit 并不是很直观...... (2认同)