python unittest中的assertRaises失败时抛出异常

6 投票
2 回答
15461 浏览
提问于 2025-04-15 13:23

我有一段代码,其中 assertRaises 在失败时会抛出一个异常。我原以为如果 assertRaises 失败了,测试就会失败,然后在最后我会看到一份报告,告诉我测试失败了。我没想到会抛出异常。下面是我的代码。我是不是做错了什么?我使用的是 Python 2.6.2。

import unittest

class myClass:

    def getName(self):

        raise myExcOne, "my exception one"
        #raise myExcTwo, "my exception two"
        #return "a"

class myExcOne(Exception):
    "exception one"

class myExcTwo(Exception):
    "exception two"


class test_myClass(unittest.TestCase):

    def setUp(self):

        self.myClass = myClass()

    def testgetNameEmpty(self):
        #self.assertRaises(myExcOne,self.myClass.getName)
        #self.assertRaises(myExcTwo,self.myClass.getName)

        try:
            self.assertRaises(myExcTwo,self.myClass.getName)
        except Exception as e:
            pass

if __name__ == "__main__":

    #unittest.main()

    suite = unittest.TestLoader().loadTestsFromTestCase(test_myClass)
    unittest.TextTestRunner(verbosity=2).run(suite)

2 个回答

6

首先,关于在 class 语句中类名后面的 (),在现代 Python 中这是完全正确的——根本不是错误。

接下来,谈谈问题的核心,assertRaises(MyException, foo) 文档中说明的,它只会捕捉到调用 foo() 时抛出的 MyException 及其子类的异常。如果抛出的异常类型不是 MyException 或其子类,那么这个异常就会继续传播。因为你的代码抛出了一个类型的异常,而你的测试却期待另一个不相关的类型,所以根据 unittest 模块的文档,抛出的异常会继续传播,引用如下:

如果抛出了 异常,测试通过;如果抛出了其他异常,则视为错误;如果没有抛出异常,则测试失败。

而“视为错误”意味着“传播其他异常”。

当你在 try/except 块中捕获到这个传播的异常时,你就消除了这个错误,unittest 就没有东西可以去诊断了。如果你的目的是将这个错误转变为失败(这是一种有争议的策略……),那么你的 except 块应该调用 self.fail

6

你发的代码有问题。首先,class myClass(): 应该改成 class myClass:。还有,if name == "main": 也需要改一下:

if __name__ == "__main__":
    unittest.main()

除了这些问题,这段代码还会出错,因为 getName() 抛出了一个叫 myExcOne 的异常,而你的测试却期待一个叫 myExcTwo 的异常。

下面是一些可以正常运行的代码。请你修改一下你问题中的代码,这样我们就能方便地复制粘贴到 Python 环境中:

import unittest

class myExcOne(Exception): "exception one"

class myExcTwo(Exception): "exception two"

class myClass:
    def getName(self):
        raise myExcTwo

class test_myClass(unittest.TestCase):
    def setUp(self):
        self.myClass = myClass()
    def testgetNameEmpty(self):
        #self.assertRaises(myExcOne,self.myClass.getName)
        self.assertRaises(myExcTwo,self.myClass.getName)

if __name__ == "__main__":
    unittest.main()

撰写回答