[Twisted-Python] Unit tests, inline callbacks, and exception handling

exarkun at twistedmatrix.com exarkun at twistedmatrix.com
Thu Sep 24 10:59:49 MDT 2009


On 04:51 pm, patrick at priority5.com wrote:
>We are using nose and the twisted.trial.unittest.TestCase class from
>Twisted 8.2.0 to write tests that use inline callbacks. In one of the
>tests, we are trying to validate that the code will behave correctly
>by raising an exception if two clients with the same user name connect
>to a server. The basic test code is similar to this:
>
>@inlineCallbacks
>def testDuplicateConnect(self):
>    server_port = random.randint(10000, 40000)
>    server = Server()
>    server.listen(port = server_port)
>
>    client1 = Client(username = "Test")
>    yield client1.connect(port = server_port)
>
>    try:
>       client2 = Client(username = "Test")
>       yield client2.connect(port = server_port)
>       assert False
>    except UsernameAlreadyExists, ex:
>       pass
>
>    yield server.close()
>    yield client.close()
>
>The test method executes and returns successfully. The exception is
>raised and caught correctly, but because a
>twisted.python.failure.Failure object was seen during deferred
>processing, twisted.trial.unittest.TestCase._cleanUp() concludes that
>an error occurred. That is perhaps not the most accurate way of
>describing what happens, but the end result is that a caught exception
>ends up being reported as an error.
>
>My question is this: are there any tips for performing exception
>handling in test methods that are decorated with @inlineCallbacks? I
>have been tracing through a lot of code trying to find any extension
>point, hook, etc. where I could indicate that the exception was caught
>correctly, but I have not found anything yet. Adding the obvious
>@raises decoration does not work because the method catches the
>exception. The closest I have come is to call
>self._observer._ignoreErrors() from the test method with the exception
>type in question, but that does not strike me as being on the right
>track.

If the problem is because the server code uses `twisted.python.log.err` 
to log the double client connection attempt, then you can make it so 
that this doesn't fail the test by flushing the error before the test 
returns, with something like this:

    self.flushLoggedErrors(UsernameAlreadyExists)

Or possibly a different exception type, depending on what exactly the 
server is logging.

If the server isn't logging anything, then I can't really know why your 
test is failing based on the example you've given.  If you can construct 
a SSCCE (<http://sscce.org>), that would help a lot.

Jean-Paul




More information about the Twisted-Python mailing list