当断言失败时继续在 Python 的单元测试中 [英] Continuing in Python's unittest when an assertion fails

查看:65
本文介绍了当断言失败时继续在 Python 的单元测试中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

切换到一个更好的例子,并阐明为什么这是一个真正的问题.

switched to a better example, and clarified why this is a real problem.

我想用 Python 编写单元测试,当断言失败时继续执行,以便我可以在单个测试中看到多个失败.例如:

I'd like to write unit tests in Python that continue executing when an assertion fails, so that I can see multiple failures in a single test. For example:

class Car(object):
  def __init__(self, make, model):
    self.make = make
    self.model = make  # Copy and paste error: should be model.
    self.has_seats = True
    self.wheel_count = 3  # Typo: should be 4.

class CarTest(unittest.TestCase):
  def test_init(self):
    make = "Ford"
    model = "Model T"
    car = Car(make=make, model=model)
    self.assertEqual(car.make, make)
    self.assertEqual(car.model, model)  # Failure!
    self.assertTrue(car.has_seats)
    self.assertEqual(car.wheel_count, 4)  # Failure!

在这里,测试的目的是确保 Car 的 __init__ 正确设置其字段.我可以将它分解为四个方法(这通常是一个好主意),但在这种情况下,我认为将其保留为测试单个概念的单个方法更具可读性(对象已正确初始化").

Here, the purpose of the test is to ensure that Car's __init__ sets its fields correctly. I could break it up into four methods (and that's often a great idea), but in this case I think it's more readable to keep it as a single method that tests a single concept ("the object is initialized correctly").

如果我们假设这里最好不要中断方法,那么我有一个新问题:我无法一次看到所有错误.当我修复 model 错误并重新运行测试时,会出现 wheel_count 错误.当我第一次运行测试时,它会节省我看到这两个错误的时间.

If we assume that it's best here to not break up the method, then I have a new problem: I can't see all of the errors at once. When I fix the model error and re-run the test, then the wheel_count error appears. It would save me time to see both errors when I first run the test.

为了进行比较,Google 的 C++ 单元测试框架区分了 在非致命的 EXPECT_* 断言和致命的 ASSERT_* 断言之间:

For comparison, Google's C++ unit testing framework distinguishes between between non-fatal EXPECT_* assertions and fatal ASSERT_* assertions:

断言成对出现,测试相同的事物但对当前函数有不同的影响.ASSERT_* 版本在失败时会产生致命的失败,并中止当前函数.EXPECT_* 版本生成非致命故障,不会中止当前函数.通常首选 EXPECT_*,因为它们允许在测试中报告多个失败.但是,如果在相关断言失败时继续操作没有意义,您应该使用 ASSERT_*.

The assertions come in pairs that test the same thing but have different effects on the current function. ASSERT_* versions generate fatal failures when they fail, and abort the current function. EXPECT_* versions generate nonfatal failures, which don't abort the current function. Usually EXPECT_* are preferred, as they allow more than one failures to be reported in a test. However, you should use ASSERT_* if it doesn't make sense to continue when the assertion in question fails.

有没有办法在 Python 的 unittest 中获得类似 EXPECT_* 的行为?如果 unittest 中没有,那么是否还有另一个支持这种行为的 Python 单元测试框架?

Is there a way to get EXPECT_*-like behavior in Python's unittest? If not in unittest, then is there another Python unit test framework that does support this behavior?

顺便说一句,我很好奇有多少现实生活中的测试可以从非致命断言中受益,所以我查看了一些 代码示例(在 2014 年 8 月 19 日编辑以使用搜索代码而不是谷歌代码搜索,RIP).在第一页随机选择的 10 个结果中,所有结果都包含在同一测试方法中进行多个独立断言的测试.所有人都将从非致命断言中受益.

Incidentally, I was curious about how many real-life tests might benefit from non-fatal assertions, so I looked at some code examples (edited 2014-08-19 to use searchcode instead of Google Code Search, RIP). Out of 10 randomly selected results from the first page, all contained tests that made multiple independent assertions in the same test method. All would benefit from non-fatal assertions.

推荐答案

获得非致命断言的另一种方法是捕获断言异常并将异常存储在列表中.然后断言该列表是空的,作为拆卸的一部分.

Another way to have non-fatal assertions is to capture the assertion exception and store the exceptions in a list. Then assert that that list is empty as part of the tearDown.

import unittest

class Car(object):
  def __init__(self, make, model):
    self.make = make
    self.model = make  # Copy and paste error: should be model.
    self.has_seats = True
    self.wheel_count = 3  # Typo: should be 4.

class CarTest(unittest.TestCase):
  def setUp(self):
    self.verificationErrors = []

  def tearDown(self):
    self.assertEqual([], self.verificationErrors)

  def test_init(self):
    make = "Ford"
    model = "Model T"
    car = Car(make=make, model=model)
    try: self.assertEqual(car.make, make)
    except AssertionError, e: self.verificationErrors.append(str(e))
    try: self.assertEqual(car.model, model)  # Failure!
    except AssertionError, e: self.verificationErrors.append(str(e))
    try: self.assertTrue(car.has_seats)
    except AssertionError, e: self.verificationErrors.append(str(e))
    try: self.assertEqual(car.wheel_count, 4)  # Failure!
    except AssertionError, e: self.verificationErrors.append(str(e))

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

这篇关于当断言失败时继续在 Python 的单元测试中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆