[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