[Twisted-Python] Writing Unittests for Twisted Applications
bh at intevation.de
Wed Dec 4 13:14:17 EST 2002
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
How difficult would it be to implement at least one of the following
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
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' 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.
Intevation GmbH http://intevation.de/
More information about the Twisted-Python