Python unittest - assertRaises的反向操作?

514 投票
11 回答
202083 浏览
提问于 2025-04-16 07:51

我想写一个测试,来确认在某种情况下不会出现异常。

测试异常是否被抛出是很简单的……

sInvalidPath=AlwaysSuppliesAnInvalidPath()
self.assertRaises(PathIsNotAValidOne, MyObject, sInvalidPath) 

……但是,怎么做相反的呢?

我想要的就是像这样……

sValidPath=AlwaysSuppliesAValidPath()
self.assertNotRaises(PathIsNotAValidOne, MyObject, sValidPath) 

11 个回答

58

只需要调用这个函数。如果它抛出一个异常,单元测试框架会把这个标记为错误。你可以加个注释,比如:

sValidPath=AlwaysSuppliesAValidPath()
# Check PathIsNotAValidOne not thrown
MyObject(sValidPath)

编辑补充了评论中的说明:

  • 单元测试有三种结果:通过、失败和错误。(如果算上XPass/XFail/跳过等,实际上会更多)
  • 如果你在测试某个特定的异常没有被抛出,但它却被抛出了,那么理论上这应该算作失败。但上面的代码把它当成了错误,这在理论上是“错误”的。
  • 从实际情况来看,出现错误时,测试运行器可能会打印出堆栈跟踪,这对调试失败很有帮助。而失败时,你可能看不到堆栈跟踪。
  • 从实际情况来看,失败的测试可以标记为“预期失败”。而错误的测试可能无法这样标记,虽然你可以把测试标记为“跳过”。
  • 从实际情况来看,让测试用例报告错误需要额外的代码。
  • “错误”和“失败”之间的区别是否重要,取决于你的工作流程。我们团队使用单元测试时,所有测试都必须通过。(我们采用敏捷编程,使用持续集成工具来运行所有单元测试)。对我们团队来说,真正重要的是“所有单元测试都通过了吗?”(也就是“Jenkins是绿色的吗?”)。所以对我们团队来说,“失败”和“错误”没有实际区别。
  • 由于上述提到的优点(代码更少,可以看到堆栈跟踪),以及我们团队对失败和错误的处理方式,我选择了这种方法。
  • 如果你以不同的方式使用单元测试,特别是如果你的工作流程对“失败”和“错误”有不同的处理,或者你想能够将测试标记为“预期失败”,那么你可能会有不同的需求。
  • 如果你希望这个测试报告为错误,可以参考DGH的回答。
88

你好 - 我想写一个测试,来确认在某种情况下不会出现异常。

这是默认的假设——异常不会被抛出。

如果你什么都不说,这在每一个测试中都是默认的。

你其实不需要为此写任何断言。

566

当然可以!请看下面的内容:

在编程中,有时候我们需要让程序做一些重复的事情,比如处理很多数据或者执行相似的操作。为了简化这个过程,我们可以使用“循环”。循环就像是一个指令,让程序不断地重复执行某段代码,直到满足某个条件为止。

比如说,如果你想让程序打印数字1到10,你可以用循环来实现,而不是手动写10次打印的指令。这样不仅节省时间,还能减少出错的机会。

另外,循环有几种不同的类型,比如“for循环”和“while循环”。“for循环”通常用于已知次数的情况,而“while循环”则适合在不知道具体次数时使用,只要满足某个条件就会继续执行。

总之,循环是编程中一个非常重要的概念,它能帮助我们更高效地完成任务。

def run_test(self):
    try:
        myFunc()
    except ExceptionType:
        self.fail("myFunc() raised ExceptionType unexpectedly!")

撰写回答