[Twisted-Python] Writing Unittests for Twisted Applications

Bernhard Herzog bh at intevation.de
Wed Dec 4 13:14:17 EST 2002


Hi all,

I've been working on a project using twisted for the last few weeks. In
the process I've written quite a few unittests most of which need to run
a twisted reactor either directly as reactor.run or via an Application
instance's run() method.

It's amazing how difficult that is, given that twisted itself has an
extensive set of unittests. Running only one test with a main loop is
simple but running several tests that need to listen and unlisten the
same ports or that have timeouts, etc. seems much more difficult than it
should be.

How difficult would it be to implement at least one of the following
features?

 1. a way to reset a reactor so that e.g. a new unit test could start
    with a clean state. It's OK for me if the unittest itself has to
    take care to do some things automatically such as disconnecting
    connections or unlistenting.

 2. A base class (derived from unittest.TestCase or as a mix-in class)
    for tests that need to run the main loop. There should perhaps be
    two of them, one for plain reactor usage and for test with
    Application instances. 

    Obviously this would require having 1. to a certain extent. However,
    it's OK if the class knew how to achieve a reset in as far as that
    is necessary for test cases. For instance, the base class could
    require that derived classes don't call the reactor directly to
    listen or to add delayed calls and go through some method instead to
    e.g. keep track of the ids returned by reactor.callLater.


AFAICT neither is currently implemented in twisted. There even seems to
be one unit test (test_sister) that's not implemented because of this.

I have effectively implemented no. 2 as part of my unit-tests but only
as much as I needed it so far. It didn't take much code but there are
some tricky things:

 1. After and unlisten when the loop has already been left, call
    reactor.iterate() to make sure the port is properly freed again.
    This was relatively easy to figure out because some twisted test
    cases do this.

 2. Application.run() will only run the reactor mainloop if main.running
    is not true. Unfortunately, main.running is not unset when
    main.shutdown or main.crash is called, so when trying to enter
    application main loops more than once, even for different
    application instances, once has to explicitly unset main.running.

My code will eventually be available under GPL as part of the
'GREAT-ER'[1] software we're developing, but it's not yet in CVS. 

If there's interest in including my test case base class in twisted I
could make it available sooner and under LGPL.


   Bernhard


[1] http://great-er.intevation.de/


-- 
Intevation GmbH                                 http://intevation.de/
Sketch                                 http://sketch.sourceforge.net/
MapIt!                                           http://www.mapit.de/




More information about the Twisted-Python mailing list