[Twisted-Python] Unit tests, inline callbacks, and exception handling
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. -Patrick -- Patrick L. Hartling Senior Software Engineer, Priority 5 http://www.priority5.com/ The information transmitted in this communication is intended only for the person or entity to which it is addressed and contains proprietary material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please destroy any copies, contact the sender and delete the material from any computer.
On 04:51 pm, patrick@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
On Sep 24, 2009, at 11:59 AM, exarkun@twistedmatrix.com wrote:
On 04:51 pm, patrick@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.
That did it. Thanks! -Patrick
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
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
-- Patrick L. Hartling Senior Software Engineer, Priority 5 http://www.priority5.com/ The information transmitted in this communication is intended only for the person or entity to which it is addressed and contains proprietary material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please destroy any copies, contact the sender and delete the material from any computer.
participants (2)
-
exarkun@twistedmatrix.com
-
Patrick Hartling