[Twisted-Python] Running twisted.trial unittests using nose

glyph at divmod.com glyph at divmod.com
Mon Aug 6 23:15:20 EDT 2007


On 6 Aug, 02:17 pm, andrew-twisted at puzzling.org wrote:
>glyph at divmod.com wrote:
>[...]
>>Twisted application does, and which is not _really_ supported by the
>>framework: re-start the reactor repeatedly.
>>
>>Eventually, 'trial' itself will not do this, and will behave as a
>>"normal" Twisted application.

Let's start with a point of agreement:
>The reactor can't be comprehensively unittested until multiple
>reactors/restartable reactors are supported anyway, so it should be 
>done.  This
>would also make it possible to consider testing multiple different 
>reactor
>implementations in a single test run.

This is absolutely true.  The limiting factors on the code being used 
this way are simply (A) a lack of reasonable tests, and (B) some 
misguided micro-optimizations in the reactor which no longer help 
anyway.  There is nothing in anyone's preferred design for Trial, mine 
included, that would preclude such a thing.

Multiple reactors should, indeed must, eventually be supported.  It 
would be nice if someone who really wanted it would implement it though, 
instead of just talking about it ;).
>I don't think this is the right approach.  The right approach is to fix 
>Twisted
>to support multiple simultaneous reactors, so that your Twisted test 
>runner that
>wants to do stuff with a reactor is isolated from the tests, and vice 
>versa.
>The tests should then use a fresh reactor for each test.  It's simple 
>and robust.

Your suggested implementation reinforces the antipattern of "tests are 
special and need 'waitFor' or 'blockOn' because they can't be written 
otherwise".  Then, of course, newbies ask why the tests can have this 
but their protocol implementation (which really needs it, seriously, 
it's not like *any* other application using Twisted) can't.  Aside from 
the fact that it might actually work / be tested, it is the same (as far 
as I'm concerned) as much of the brokenness that Trial has dealt with 
for quite some time.

Much code within and without Twisted uses, and will continue for the 
forseeable future to use, "from twisted.internet import reactor" to 
access the reactor.  One might hope that this usage would eventually be 
replaced by something better, but it's not clear if this (or an 
equivalent spelling) could ever be *completely* eliminated.  I quite 
like Jim Fulton's suggestion for adding an ITransport.reactor attribute 
and using that in most places where the global import is currently used. 
However, even if we had a comprehensive somehow non-global way to get at 
a reactor available today, there would still be a *very* lengthy 
transition period to a new API.  The question will remain what to do 
about that code.

My main objection here, though, is that I'd really like to be able to 
add nifty Twisted-using features to Trial, and it's basically impossible 
right now, due in large part to the fact that the reactor keeps starting 
and stopping.  Creating a new reactor for each test is going to create 
confusing semantics for code written using established idioms, because 
either the framework is going to go to a lot of trouble to fool 
everything into using trial's idea of the reactor the tests should be 
using (which begs the question: how do you test trial itself, if it has 
a reference to the "real" reactor?), or it's going to require special 
hacks to get at the "real" reactor which still won't behave in an event- 
driven way if a test (shock, horror) actually does want to do some real 
I/O itself.  Although I am *personally* focusing on how to write better 
and more isolated unit tests using trial, I know of a small number of 
people using it as an integration testing tool that does tons of I/O to 
external systems and I think that is an interesting use-case and should 
be better supported, not worse.

Perhaps the 'trial' tool itself is a misguided design though, and 
'disttrial' will simply replace it in short order.  If this is the case, 
then the tests are running in a subprocess anyway, and there's no reason 
to run any code in-process with the tests, except for things to gather 
metrics.  In that case, the 'disttrial' tool itself is a real Twisted 
program, and the subprocess fakes just enough to get by:

http://twistedmatrix.com/trac/browser/branches/disttrial-1784/twisted/trial/dist/slavetrial.py#L60

That *particular* hack makes me cringe, but I think the overall 
architecture may satisfy us both better in the end.




More information about the Twisted-Python mailing list