[erlang-questions] testing asynchronous code
Scott Lystig Fritchie
fritchie@REDACTED
Mon Apr 19 22:48:28 CEST 2010
Martin, you have another option: your test code calls
YourModule:handle_cast() directly. If your client side stub looks like:
client_side_stub(Server, Args) ->
gen_server:cast(Server, {some_tag, Args}).
Then refactor to this and export both client_side_stub() and
make_some_tag().
client_side_stub(Server, Args) ->
gen_server:cast(Server, make_some_tag(Args)).
make_some_tag(Args) ->
{some_tag, Args}.
Now your testing code can do:
OldState = YourModule:init(WhateverArgsYouNeed),
case YourModule:handle_cast(YourModule:make_sometag(Args), OldState) of
{noreply, State} ->
verify_state_is_sane(State);
{noreply, State, Timeout} ->
%% Your code may not use this return tuple...
verify_state_is_sane(State);
{stop, Reason, State} ->
%% Your code may not use this return tuple either
verify_state_is_sane(State);
The above code is has lots of cut-and-paste redundancy that you can
factor out, if you wish. Or you can use the skeleton as-is, allowing
the test code to check that the {noreply, State, Timeout} is indeed
correct in some cases and {noreply, State} correct in other cases.
There's only a little bit of glue code yet to write to grow into
something like this:
OldState = YourModule:init(WhateverArgsYouNeed),
State = fold_async_messages(YourModule, OldState,
[cast_message_number_1,
{cast_message_2, Args},
{cast_message_foo, Args, More, Stuff}]),
ok = verify_state_is_sane(State).
Or perhaps you want to be able to pull the State out of an
already-running gen_server process and test it like the above. Go
ahead, create this:
handle_call(get_internal_state, _From, State) ->
{reply, State, State};
Now your testing code can use
verify_state_is_sane(gen_server:call(Server, get_internal_state)).
Or perhaps you'd rather embed verify_state_is_sane() inside the
gen_server? Your test code can do this call, but the rest of the client
API will ignore it.
handle_call(check_internal_state, _From, State) ->
ok = verify_internal_state(State),
{reply, yup_looks_wonderful, State};
Hope this helps.
-Scott
More information about the erlang-questions
mailing list