如何在Erlang中测试gen server?

4

我是一个Erlang的初学者,我编写了一个基本的gen server程序如下,我想知道如何测试服务器,以便我可以知道它是否正常工作。

-module(gen_server_test).
-behaviour(gen_server).
-export([start_link/0]).
-export([alloc/0, free/1]).
-export([init/1, handle_call/3, handle_cast/2]).
start_link() ->
    gen_server:start_link({local, gen_server_test}, ch3, [], []).
alloc() ->
    gen_server:call(gen_server_test, alloc).
free(Ch) ->
    gen_server:cast(gen_server_test, {free, Ch}).
init(_Args) ->
    {ok, channels()}.
handle_call(alloc, _From, Chs) ->
    {Ch, Chs2} = alloc(Chs),
    {reply, Ch, Chs2}.
handle_cast({free, Ch}, Chs) ->
    io:format(Ch),
        io:format(Chs),
        Chs2 = free(),
    {noreply, Chs2}.

free() -> 
        io:format("free").
channels() ->
        io:format("channels").
alloc(chs) -> 
        io:format("alloc chs").

顺便说一下:该程序可以编译,但并不是一个好的程序,我只是想打印一些东西以确保它能够正常工作 :)


你能澄清一下“测试服务器以确保其正常工作”的意思吗?你试图寻找哪些测试用例/问题来源? - elliot42
2个回答

8
一个实现gen_server的模块之美在于它只是一个回调模块。你甚至不需要生成底层的gen_server进程来测试它。
你需要做的就是让你的测试框架(通常是eunit)通过注入不同的输入(不同的gen_server状态、不同的输入消息)等来调用所有的handle_call/cast/info函数,并确保它返回正确的响应元组(例如{reply, ok, NewState}或{noreply, NewState}等)。
当然,如果你的回调函数不是纯函数,这种方法就不能完美地工作。例如,在你的handle_call函数中,如果你发送了一个消息给另一个进程,或者如果你修改了一个ets表。在这种情况下,你必须确保在运行测试之前预先创建所有所需的进程和表。

2
你可以尝试以下方法之一:
  1. 使用erlang shell并手动调用命令。确保源代码或者.beam文件在Erlang路径中(参数-pz),例如:erl -pz <path here>

  2. 编写一个EUnit测试用例

PS:我认为你的代码有误,因为你似乎将模块ch3作为服务器启动了,而不是gen_server_test模块。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接