[Twisted-Python] Testing function with delayed calls

Mashiat Sarker Shakkhar mashiat.sarker at gmail.com
Fri Oct 2 08:33:53 MDT 2015


On Thu, Oct 1, 2015 at 5:46 PM, Ashwini Oruganti <ashfall at twistedmatrix.com>
wrote:

>
>
> On Thu, Oct 1, 2015 at 1:40 PM, Mashiat Sarker Shakkhar <
> mashiat.sarker at gmail.com> wrote:
>
>> Hi
>>
>> I have a function that uses callLater extensively to schedule a number of
>> different tasks. I don't want to get into the rationale behind such a
>> design, but here is a contrived example which will help me explain my
>> problem:
>>
>>
>>     def b():
>>
>>         '''Do some work'''
>>
>>
>>     def c():
>>
>>         '''Do some more work'''
>>
>>
>>     def a(flag):
>>
>>         if flag:
>>
>>             return Reactor.callLater(300, b)
>>
>>         else:
>>
>>             return Reactor. callLater(100, c)
>>
>>
>> Now I want to test this function. Of course I can't wait for 5 minutes to
>> ensure that `b` or `c` will indeed be called. What I need is some sort of
>> mock clock which lets me fast forward time. Does any such thing exist in
>> Twisted / Trial?
>>
>
> Yes there is! `MemoryReactorClock.advance`
> https://twistedmatrix.com/documents/current/api/twisted.test.proto_helpers.MemoryReactorClock.html
> does this for you.
>
>
HI Ashwini

 Thanks a lot for your response. I did come across MemoryReactorClock
before, but I could not figure out how to use it to test my code. I am
using trial as the test runner, which allows me to pass the name of the
reactor to be used in command line. But MemoryReactorClock is not
available, because it is not in twisted.internet.

The code that I am testing imports reactor from twisted.internet in the
global scope. Do I have to change that and pass a reactor explicitly (say,
as a function parameter) where it is needed? Is there any other way to
change the default reactor to MemoryReactorClock just for running tests?

Going with my previous example, do I have to rewrite the code like
following or is there a better way?

    def b():

        '''Do some work'''


    def c():

        '''Do some more work'''


    def a(myreactor, flag):

        if flag:

            return myreactor.callLater(300, b)

        else:

            return myeactor. callLater(100, c)


I do see this in the documentation:

> New application code should prefer to pass and accept the reactor as a
parameter where it is needed, rather than relying on being able to import
this module to get a reference. This simplifies unit testing ...


But I'd prefer not to change the signature of existing functions.


Regards

Shakkhar
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/twisted-python/attachments/20151002/9fcd1849/attachment-0002.html>


More information about the Twisted-Python mailing list