开发者

Erlang: How should I test this?

开发者 https://www.devze.com 2022-12-16 23:33 出处:网络
I\'ve got an application where I cast a message to a gen_server to start an operation, then I call the gen_server every second to gather intermediate results until the operation completes. In producti

I've got an application where I cast a message to a gen_server to start an operation, then I call the gen_server every second to gather intermediate results until the operation completes. In production, it usually takes a couple of minutes, but it's only limited by the input size and I'd like to test hour long operations, too.

I want to always make sure this operation stil开发者_StackOverflow中文版l works by running a test as needed. Ideally, I'd like to run this test multiple times with different inputs, also.

I use eunit right now, but it doesn't seem to have a purpose-built way of exercising this scenario. Does commmon test provide for this? Is there an elegant way of testing this or should I just hack something up? In general, I'm having trouble wrapping my head around how to systematically test stateful, asynchronous operations in Erlang.


Yes, common test will do this.

This is a cut down version of the common test suite skeleton that our erlang emacs mode provides (you can use the normal erlang one or erlware one):

-module(junk).

%% Note: This directive should only be used in test suites.
-compile(export_all).

-include("test_server.hrl").

%%
%% set up for the suite...
%%
init_per_suite(Config) ->
    Config.

end_per_suite(_Config) ->
    ok.

%%
%% setup for each case in the suite - can know which test case it is in
init_per_testcase(_TestCase, Config) ->
    Config.

end_per_testcase(_TestCase, _Config) ->
    ok.

%%
%% allows the suite to be programmatically managed
%%
all(doc) ->
    ["Describe the main purpose of this suite"];

all(suite) ->
    [].

%% Test cases starts here.
%%--------------------------------------------------------------------
test_case(doc) ->
    ["Describe the main purpose of test case"];

test_case(suite) ->
    [];

test_case(Config) when is_list(Config) ->
    ok.

There are 2 basic ways you could do it.

First up start the gen_server in init_per_suite/1 and then have a large number of atomic tests that act on that long running server and then tear the gen_server down in end_per_suite/1. This is the preferred way - your gen_server should be long-running and persistent over many transactions, blah-blah...

The other way is to make a singleton test and start the gen_server with init_per_testcase/2 and tear it down in end_per_testcase/2


Testing Stateful Asynchronous operations is hard in any language, Erlang or otherwise.

I would actuall recommend using etap and have the asynchronous tests run a callback that will then run etap:end_tests()

Since etap uses a running test server and it waits for the end_test call you have a little more control for asynchronous tests.

0

精彩评论

暂无评论...
验证码 换一张
取 消