[erlang-questions] Testing gen_statem timers

Torben Hoffmann torben.lehoff@REDACTED
Tue Aug 20 15:30:31 CEST 2019

On Fri, 16 Aug 2019 at 15:47, Raimo Niskanen <
raimo+erlang-questions@REDACTED> wrote:

> > But the problem of mocking still remains the same.
> > When testing I prefer to mock time so that I don't have to wait for the
> > timeout to occur.
> > Furthermore, I'm so heavily influenced by my ten years at Motorola that I
> > want the timers to stand out as in all the nice SDL diagrams in the
> > standards shows.
> > That means that I want an easy way to check that a timer has been started
> > (mock the call to chronos:start_timer()) and then an easy way to induce
> the
> > expiry of said timer without having to wait for whatever the delay is.
> > When you have timers in the minutes range you just don't want your
> > automated tests to wait it out.
> >
> > If there is a way to avoid this with gen_statem I'd be most interested!
> Not today.
> For debugging only, not mocking, it would be possible to log timer actions
> in the sys log, and to include timer statistics i.e the number of running
> timers or a list of them in sys:get_status/1.
> Would that be interesting fetures?
> For mocking, a possible new feature would be to make the calls to
> erlang:start_timer/4 and erlang:cancel_timer/1 pluggable, i.e call them
> through fun:s.  Then the plugged in functions may for example communicate
> with a registered timer server that can do as it pleases about when to
> fire timeouts, log timer starts and cancels, etc...
> How dynamic would such a feature need to be?
> * An option to gen_statem:start{,_link}/3,4?
> * Read application variable at server start?
> * Return an action from the callback module (so the callback module
>   can implement a function to activate mocking)?
> * Other suggestions?
> Interesting topic - I did not forsee this need...
> BRs
> / Raimo

I like the idea of making the calls to start an cancel timers pluggable.

The key requirement is that there is a function call that one can detect
and that the start of a timer doesn't actually trigger the creation of a
timer since one needs the ability to inject the timer expiry into the
gen_statem when the test calls for it.
On that note it might not be good to just expose the erlang:*_timer()
functions as they would be un-mockable.
Maybe something like a call to a dummy function when the timers
start/cancel. That can be mocked or spotted by a trace.
And then a way to inject by using a function in the gen_statem module that
would only work in timers_testing mode.
I would welcome this as an option to gen_statem:start{,_link}/3,4 that one
would only use for testing. It should simply turn the erlang:*_timer()
calls into calls to those dummy functions.

This seems like the least invasive way of doing it. And then we can all
expect a beer from the first person to ship to production with the
testing_timers option ;-)

Given that gen_statem has introduced the notion of generic timeouts a
mechanism such as the above would render Chronos superfluous when it comes
to testing timers with gen_statem.
I would welcome that despite all the help I have gotten from Chronos over
the years.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20190820/b66c9943/attachment.htm>

More information about the erlang-questions mailing list