[erlang-questions] Unidirectional architectures in Erlang

Rodrigo Stevaux roehst@REDACTED
Fri Aug 31 18:51:31 CEST 2018


yes, we fundamentally are trying to do integration testing.

unit testing process communication pairwise by sending a message to the
parent process is something we tried to do and it worked reasonably well.
but we want to know that the whole composition of processes works well.

the challenge we found on that approach is that the processes have names
and we would have to find a way to inject the pid of the "next" process in
the chain and make it the test process during testing and other process
during production (which can be done with a little bit of instrumentation
and conditional compiling -- we are on Elixir actually).

is using the "sys" module a regular practice?

thanks for the reply.

Em qui, 30 de ago de 2018 às 20:33, Fred Hebert <mononcqc@REDACTED> escreveu:

> On 08/30, Rodrigo Stevaux wrote:
> >Message comes in, logic applies, message goes out.
> >The generic servers are very easy to test in a pure fashion: just test the
> >return values of handle_call for a given state.
> >
>
> That can be done as a regular unit test, yes.
>
> >But:
> >- unit testing should test that the unit under test forwards a message to
> a
> >given address (and that is not reflected on the handle_call return value)
>
> Aside from using mocks to know that the proper function calls have taken
> place, you can't easily test the forwarding of messages since that would
> imply side-effects turning your unit tests into integration tests.
>
> >- doing the integration testing of a "pipeline" of process involves
> testing
> >that ultimately a message gets to the last process.
> >
>
> Yes and no. You can test that each element of the chain properly
> forwards data to the right destination. You can do that if you make the
> endpoint/address/destination for each forwarded message parametrizable
> or configurable. Forward the data to the test process instead to confirm
> that the right side-effect has taken place.
>
> This lets you test each section of the chain in isolation; then if all
> sections are well-behaved, you can infer that the whole chain should
> behave well. You can confirm that with a more naive end-to-end test,
> knowing that individual components are tested more thoroughly.
>
> >Given the maturity of Erlang, I'd expect to promptly find solutions to
> this
> >case.
>
> On top of the techniques above, you can try using the `sys' module to
> introspect all OTP behaviours and look at their transitions as a neutral
> observer:
>
>     1> sys:get_status(disk_log_server).
>     {status,<0.75.0>,
>             {module,gen_server},
>             [[{<0.76.0>,'$#group_history'},
>               {'$initial_call',{disk_log_server,init,1}},
>               {'$ancestors',[kernel_safe_sup,kernel_sup,<0.45.0>]}],
>              running,<0.66.0>,[],
>              [{header,"Status for generic server disk_log_server"},
>               {data,[{"Status",running},
>                      {"Parent",<0.66.0>},
>                      {"Logged events",[]}]},
>               {data,[{"State",{state,[]}}]}]]}
>     2> P = self(),
>     2> sys:install(
>     2>   disk_log_server,
>     2>   {fun(_Acc, Event, State) -> P ! {trace, Event, State} end,
>     2>    nodata}
>     2> ).
>     ok
>     3> disk_log_server ! fake_data.
>     fake_data
>     4> flush().
>     Shell got {trace,{in,fake_data},disk_log_server}
>     Shell got {trace,{noreply,{state,[]}},disk_log_server}
>     ok
>
> Those won't let you see arbitrary calls being made, but if you have a
> process chain A -> B -> C, then you can, by looking at the traces of all
> three processes, track the history of a call and the consequences they
> have.
>
> The sys module is full of really cool functionality few people know
> about, and that can make live debugging, but also testing much simpler.
>
> >
> >I haven't found a nice solution yet, so I suppose I am using OTP in a
> wrong
> >way (maybe it's not a good fit for my project), or I am choosing the wrong
> >architecture, or that I am missing key knowledge about how to test things
> >in Erlang.
>
> There aren't enough details to know at this point. I frequently just use
> `meck' (https://github.com/eproxus/meck) as a library, which lets you
> replace arbitrary function calls through hot code loadig, get traces and
> counts of all calls and values returned of unmodified code, and so on.
>
> If what you're looking for is a way to track side-effects in a very
> whitebox manner, meck is hard to beat.
>
> >
> >Can anyone shed some light on this questions? Thanks in advance!
>
> please provide more details about the nature of the side-effects you are
> trying to observe in a unit test. My default reflex would be to say that
> the moment you're testing side-effects, you are doing integration
> testing.
>
> Regards,
> Fred.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20180831/11f79211/attachment.htm>


More information about the erlang-questions mailing list