In order to make sure that the error messages from my module are informative, I would like to see all the error messages caught by assertRaises(). Today I do it for each assertRaises(), but as there are lots of them in the test code it gets very tedious.
How can I print the error messages for all the assertRaises()? I have studied the documentation on http://docs.python.org/library/unittest.html without figuring out how to solve it. Can I somehow monkeypatch the assertRaises() method? I prefer not to change all the assertRaises() lines in the test code, as I most often use the test code the standard way.
I guess this question is related to Python unittest: how do I test the argument in an Exceptions?
This is how I do it today. For example:
#!/usr/bin/env python def fail(): raise ValueError('Misspellled errrorr messageee')
And the test code:
#!/usr/bin/env python import unittest import failure class TestFailureModule(unittest.TestCase): def testFail(self): self.assertRaises(ValueError, failure.fail) if __name__ == '__main__': unittest.main()
To check the error message, I simply change the error type in the assertRaises() to for example IOError. Then I can see the error message:
E ====================================================================== ERROR: testFail (__main__.TestFailureModule) ---------------------------------------------------------------------- Traceback (most recent call last): File "test_failure.py", line 8, in testFail self.assertRaises(IOError, failure.fail) File "/usr/lib/python2.7/unittest/case.py", line 471, in assertRaises callableObj(*args, **kwargs) File "/home/jonas/Skrivbord/failure.py", line 4, in fail raise ValueError('Misspellled errrorr messageee') ValueError: Misspellled errrorr messageee ---------------------------------------------------------------------- Ran 1 test in 0.001s FAILED (errors=1)
Any suggestions? /Jonas
EDIT:
With the hints from Robert Rossney I managed to solve the problem. It is not mainly intended for spelling errors, but for making sure that the error messages are really meaningful for the user of the module. The normal functionality of unittest (this is how I use it most of the time) is achieved by setting SHOW_ERROR_MESSAGES = False.
I simply override the assertRaises() method, as seen below. It works like charm!
SHOW_ERROR_MESSAGES = True class NonexistantError(Exception): pass class ExtendedTestCase(unittest.TestCase): def assertRaises(self, excClass, callableObj, *args, **kwargs): if SHOW_ERROR_MESSAGES: excClass = NonexistantError try: unittest.TestCase.assertRaises(self, excClass, callableObj, *args, **kwargs) except: print '\n ' + repr(sys.exc_info()[1])
A fraction of the resulting output:
testNotIntegerInput (__main__.TestCheckRegisteraddress) ... TypeError('The registeraddress must be an integer. Given: 1.0',) TypeError("The registeraddress must be an integer. Given: '1'",) TypeError('The registeraddress must be an integer. Given: [1]',) TypeError('The registeraddress must be an integer. Given: None',) ok testCorrectNumberOfBytes (__main__.TestCheckResponseNumberOfBytes) ... ok testInconsistentLimits (__main__.TestCheckNumerical) ... ValueError('The maxvalue must not be smaller than minvalue. Given: 45 and 47, respectively.',) ValueError('The maxvalue must not be smaller than minvalue. Given: 45.0 and 47.0, respectively.',) ok testWrongValues (__main__.TestCheckRegisteraddress) ... ValueError('The registeraddress is too small: -1, but minimum value is 0.',) ValueError('The registeraddress is too large: 65536, but maximum value is 65535.',) ok testTooShortString (__main__.TestCheckResponseWriteData) ... ValueError("The payload is too short: 2, but minimum value is 4. Given: '\\x00X'",) ValueError("The payload is too short: 0, but minimum value is 4. Given: ''",) ValueError("The writedata is too short: 1, but minimum value is 2. Given: 'X'",) ValueError("The writedata is too short: 0, but minimum value is 2. Given: ''",) ok testKnownValues (__main__.TestCreateBitPattern) ... ok testNotIntegerInput (__main__.TestCheckSlaveaddress) ... TypeError('The slaveaddress must be an integer. Given: 1.0',) TypeError("The slaveaddress must be an integer. Given: '1'",) TypeError('The slaveaddress must be an integer. Given: [1]',) TypeError('The slaveaddress must be an integer. Given: None',) ok
To catch and print an exception that occurred in a code snippet, wrap it in an indented try block, followed by the command "except Exception as e" that catches the exception and saves its error message in string variable e . You can now print the error message with "print(e)" or use it for further processing.
Internally, unittest. main() is using a few tricks to figure out the name of the module (source file) that contains the call to main() . It then imports this modules, examines it, gets a list of all classes and functions which could be tests (according the configuration) and then creates a test case for each of them.
There are two ways you can use assertRaises: using keyword arguments. Just pass the exception, the callable function and the parameters of the callable function as keyword arguments that will elicit the exception. Make a function call that should raise the exception with a context.
I once preferred the most excellent answer given above by @Robert Rossney. Nowadays, I prefer to use assertRaises as a context manager (a new capability in unittest2) like so:
with self.assertRaises(TypeError) as cm: failure.fail() self.assertEqual( 'The registeraddress must be an integer. Given: 1.0', str(cm.exception) )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With