【发布时间】:2011-06-11 14:17:06
【问题描述】:
编辑:切换到一个更好的例子,并阐明了为什么这是一个真正的问题。
我想用 Python 编写单元测试,当断言失败时继续执行,这样我就可以在单个测试中看到多个失败。例如:
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__ 正确设置其字段。我可以将其分解为四种方法(这通常是个好主意),但在这种情况下,我认为将其保留为测试单个概念的单个方法(“对象已正确初始化”)更具可读性。
如果我们假设最好不要分解该方法,那么我有一个新问题:我无法一次看到所有错误。当我修复model 错误并重新运行测试时,会出现wheel_count 错误。当我第一次运行测试时,这样可以节省我查看这两个错误的时间。
为了比较,Google 的 C++ 单元测试框架 distinguishes between 在非致命的EXPECT_* 断言和致命的ASSERT_* 断言之间:
断言成对出现,测试相同的东西,但对当前函数有不同的影响。 ASSERT_* 版本在失败时会产生致命失败,并中止当前功能。 EXPECT_* 版本生成非致命故障,不会中止当前功能。通常 EXPECT_* 是首选,因为它们允许在测试中报告多个失败。但是,如果在相关断言失败时继续没有意义,您应该使用 ASSERT_*。
有没有办法在 Python 的 unittest 中获得类似 EXPECT_* 的行为?如果不在unittest 中,那么是否有另一个 Python 单元测试框架支持这种行为?
顺便说一句,我很好奇有多少实际测试可以从非致命断言中受益,所以我查看了一些code examples(2014-08-19 编辑,使用搜索代码而不是 Google 代码搜索,RIP)。从第一页随机选择的 10 个结果中,所有测试都包含在同一测试方法中做出多个独立断言的测试。所有人都将从非致命断言中受益。
【问题讨论】:
-
你最后做了什么?我对这个话题很感兴趣(出于完全不同的原因,我很乐意在比评论更宽敞的地方讨论)并且想知道你的经历。顺便说一句,“代码示例”链接以“可悲的是,此服务已被关闭”结尾,所以如果您有缓存版本,我也有兴趣查看它。
-
供以后参考,我相信this是当前系统上的等价搜索,但结果不再如上述。
-
@Davide,我最终什么都没做。 “每个方法只做一个断言”的方法对我来说似乎过于教条,但唯一可行(和可维护)的解决方案似乎是 Anthony 的“catch and append”建议。不过,这对我来说太难看了,所以我只是坚持每个方法都有多个断言,而且我必须忍受运行测试的次数超过发现所有故障所需的次数。
-
名为 PyTest 的 python 测试框架非常直观,默认显示所有断言失败。这可能是解决您面临的问题的方法。
标签: python unit-testing