简体   繁体   中英

python unittest combine assertions with context manager

To test a function, where I raise an exception when the first argument is not of integer type:

def magicWithInteger(integerA):
    if not isinstance(integerA, int):
        raise TypeError("argument should be integer type")

I use unittest assertRaises AND assertEqual, so I can check if the function with wrong argument raises the TypeError AND if the TypeError actually spits out "argument should be integer type"

class test(unittest.TestCase):

    def test_magicWithInteger(self):
        self.assertRaises(TypeError, MagicWithInteger, "TEST")
        try:
            MagicWithInteger("TEST")
        except TypeError as error:
            self.assertEqual(str(error), "argument should be integer type")

It looks a bit silly to call the function twice, first to check if it raises the exception and second to check which TypeError exception?
After some research, I know it should be possible to do these two tests in one go with context manager, but I can not seem to make ends meet...

You can use a with self.assertRaises(ExceptionType) context manager to catch the exception. According to the assertRaises manual , you can then look at the exception after the with block: it appears to still be in scope if you give it a name with the as <name> syntax:

with self.assertRaises(SomeException) as cm:
    do_something()

the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3)

Source: docs.python.org

So your code would become:

class test(unittest.TestCase):
    def test_magicWithInteger(self):
        with self.assertRaises(TypeError) as cm:
            MagicWithInteger("TEST")
        self.assertEqual(str(cm.exception), "argument should be integer type")

PS: I wasn't aware of this, but the with statement does not introduce a new scope in Python. Variables defined inside with are in the same scope as the with statement itself. See https://stackoverflow.com/a/45100308/3216427 to this specific point and, for what actually creates scopes, https://stackoverflow.com/a/52992404/3216427 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM