如何在 erlang 中测试 gen 服务器?
我是 erlang 的初学者,我编写了一个基本的 gen 服务器程序,如下所示,我想知道如何测试服务器,以便我知道它运行良好。
-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").
顺便说一句:该程序可以编译,但这不是一个好程序,我只是想打印一些东西以确保它有效:)
I am a beginner with erlang, and i write a basic gen server program as follows, I want to know, how to test the server so i can know it works well.
-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").
BTW: The program can be compiled, and it is not a good program, I just want to print something to make sure it works :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
gen_server 实现模块的优点在于它只是一个回调模块。人们甚至不需要生成底层的 gen_server 进程来测试它。
您需要做的就是让您的测试框架(通常是 eunit)通过注入不同的输入(不同的 gen_server 状态、不同的输入消息)等来调用所有的 handle_call/cast/info 函数,并确保它返回正确的响应元组(例如 {reply, ok, NewState} 或 {noreply, NewState} 等)
当然,如果你的回调函数不是 纯函数。例如,在您的handle_call函数中,如果您正在向另一个进程发送消息,或者您正在修改ets表。在这种情况下,您必须确保在运行测试之前预先创建所有必需的进程和表。
The beauty of a gen_server implementing module is that it is just a callback module. One need not even have to spawn the underlying gen_server process to test it.
All you need to do is have your test framework (usually eunit) to invoke all the handle_call/cast/info functions by injecting it with different inputs (different gen_server states, different input messages) etc. and ensure it returns the correct response tuple (for eg. {reply, ok, NewState} or {noreply, NewState} etc.)
Ofcourse, this wouldnt work perfectly if your callback functions arn't pure functions. For eg., in your handle_call function, if you are sending a message to another process for eg., or if you are modifying an ets table. In which case, you have to ensure that all the required processes and tables are pre-created before running the test.
您可以尝试以下操作之一:
使用 erlang shell 并手动调用命令。确保源文件或 .beam 文件位于 Erlang 路径中(参数
-pz
,如下所示:erl -pz
)编写 EUnit 测试用例
PS:我认为你有一个错误您的代码,因为您似乎将模块
ch3
作为服务器启动,而不是gen_server_test
模块。You could try one of the following:
Use the erlang shell and invoke the commands manually. Make sure the source or .beam file is in the Erlang path (parameter
-pz
, like this:erl -pz <path here>
)Write an EUnit test case
PS: I think you have an error in your code, because you seem to start the module
ch3
as the server, not thegen_server_test
module.