How to show the error messages caught by assertRaises() in unittest in Python2.7?

前端 未结 5 1313
长情又很酷
长情又很酷 2020-12-07 18:27

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 ass

相关标签:
5条回答
  • 2020-12-07 18:41

    Out-of-the-box unittest doesn't do this. If this is something you want to do frequently, you can try something like this:

    class ExtendedTestCase(unittest.TestCase):
    
      def assertRaisesWithMessage(self, msg, func, *args, **kwargs):
        try:
          func(*args, **kwargs)
          self.assertFail()
        except Exception as inst:
          self.assertEqual(inst.message, msg)
    

    Derive your unit test classes from ExtendedTestCase instead of unittest.TestCase.

    But really, if you're simply concerned about misspelled error messages, and concerned enough to want to build test cases around it, you shouldn't be inlining messages as string literals. You should do with them what you do with any other important strings: defining them as constants in a module that you import and that someone is responsible for proofreading. A developer who misspells words in his code will also misspell them in his test cases.

    0 讨论(0)
  • 2020-12-07 18:45

    You are looking for assertRaisesRegex, which is available since Python 3.2. From the docs:

    self.assertRaisesRegex(ValueError, "invalid literal for.*XYZ'$",
                           int, 'XYZ')
    

    or:

    with self.assertRaisesRegex(ValueError, 'literal'):
        int('XYZ')
    

    PS: if you are using Python 2.7, then the correct method name is assertRaisesRegexp.

    0 讨论(0)
  • 2020-12-07 18:56

    If you want the error message exactly match something:

    with self.assertRaises(ValueError) as error:
      do_something()
    self.assertEqual(error.exception.message, 'error message')
    
    0 讨论(0)
  • 2020-12-07 19:00

    mkelley33 gives nice answer, but this approach can be detected as issue by some code analysis tools like Codacy. The problem is that it doesn't know that assertRaises can be used as context manager and it reports that not all arguments are passed to assertRaises method.

    So, I'd like to improve Robert's Rossney answer:

    class TestCaseMixin(object):
    
        def assertRaisesWithMessage(self, exception_type, message, func, *args, **kwargs):
            try:
                func(*args, **kwargs)
            except exception_type as e:
                self.assertEqual(e.args[0], message)
            else:
                self.fail('"{0}" was expected to throw "{1}" exception'
                          .format(func.__name__, exception_type.__name__))
    

    Key differences are:

    1. We test type of exception.
    2. We can run this code both on Python 2 and Python 3 (we call e.args[0] because errors in Py3 don't have message attribute).
    0 讨论(0)
  • 2020-12-07 19:07

    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)
    )
    
    0 讨论(0)
提交回复
热议问题