在单元测试 python 中失败的情况下运行测试用例



我有一个Python的testSuite,其中包含几个使用单元测试框架的测试用例。我正在使用导入单元测试

如果测试用例中的测试步骤失败,则测试用例将进入拆解类。即使一个测试用例失败,我也想继续测试用例的其余部分。

单元测试的默认行为:如果任何测试步骤失败,它将关闭类并结束测试用例。

测试步骤:我的意思是断言相等,就像这个内置的过程一样,它定义了它是失败还是通过

考虑到你有这样的东西:

class TestFoo(unittest.TestCase):
def test_case_1(self):
self.assertEqual(1, 2)
self.assertEqual(1, 3)
self.assertEqual(1, 1)

第一个断言将失败,接下来的断言不会运行,但测试将结束,并且将调用 self.tearDown 方法。

当你断言时,你的意思是条件是强行正确的,或者继续下去没有意义。你的意思是:"如果一个人不等于两个,那么生活就不再有意义了......":)

大多数时候都是这种情况。例如,如果结果代码不是预期的结果代码,则不希望检查 rest API 的结果正文。

您应该一步测试所有等式,以确保它们都将被检查。您可以将它们分组为元组,例如:

class TestFoo(unittest.TestCase):
def test_case_1(self):
self.assertEqual((1, 1, 1), (2, 3, 1))

然后你会得到这样的输出:

AssertionError: Tuples differ: (1, 1, 1) != (2, 3, 1)
First differing element 0:
1
2
- (1, 1, 1)
?  ^  ^
+ (2, 3, 1)
?  ^  ^

从 python 文档中:

assertEqual(first, second, msg=None) 测试第一个和第二个是否相等。如果值比较不相等,测试将失败

此外,如果第一个和第二个是完全相同的类型并且 列表、元组、字典、集合、冻结集或 str 或子类的任何类型的 向 addTypeEqualFunc() 注册特定于类型的相等 将调用函数以生成更有用的默认值 错误消息(另请参阅特定于类型的方法列表)。

https://docs.python.org/2/library/unittest.html#unittest.TestCase.assertEqual https://docs.python.org/3.6/library/unittest.html#unittest.TestCase.assertEqual

[编辑] - 在对此问题进行一些澄清后,评论本身,但还没有代码示例。

考虑到您有一些不同的东西,例如:

class TestBar(unittest.TestCase):
def test_rest_api_foo(self):
r = request("http://dummyurl")
self.assertEqual(r.status_code, 200)
self.assertEqual(r.text, "hello world")

您可以做许多(hacky)事情,例如计算失败次数,而不是在最后断言和断言计数器值:

class TestBar(unittest.TestCase):
def test_rest_api_foo(self):
r = request("http://dummyurl")
errors = (r.status_code != 200)
errors += (r.text != "hello world")
self.assertEqual(errors, 0)

或者创建一个帮助程序函数来断言、记录、计数和吞噬异常,然后在最后断言计数器。有很多可能性。

但是,一般来说,最好的(最简单,最清晰,最无聊的)方法是评论中已经建议的方法:

class TestBar(unittest.TestCase):
def test_rest_api_status_code_foo(self):
r = request("http://dummyurl")
self.assertEqual(r.status_code, 200)
def test_rest_api_text_foo(self):
r = request("http://dummyurl")
self.assertEqual(r.text, "hello world")

请注意,在此特定示例中,单个测试用例会更好。

无论如何,这将为您提供单独的错误消息,同时保持代码简单且易于维护。

如果你的问题,否则,是因为在每个测试用例之后调用了tearDown方法,那么你可以使用tearDownClass进行清理(python3或来自unittest2)。

我敢肯定,我还没有在这里涵盖您的实际问题的所有可能性,但也许这对于显示您的开放性问题有多少可能性很有用。所以,请澄清你的问题。

subTest怎么样?

import unittest

class TestFoo(unittest.TestCase):
def test_bar(self):
with self.subTest('Failed'):
self.assertEqual(5, 2 + 2)
with self.subTest('Passed'):
self.assertEqual(1, 1)

Olivecode的例子将如下所示:

class TestBar(unittest.TestCase):
def test_rest_api_foo(self):
r = request("http://dummyurl")
with self.subTest('Test status code'):
self.assertEqual(r.status_code, 200)
with self.subTest('Test text'):
self.assertEqual(r.text, "hello world")

好问题! 当assert*助手在unittest(或pytest,一个常见的 Python 测试框架)中失败时,没有内置的方法可以继续。

实现相同效果的最惯用方法是一次使用比较字典或值元组。

class TestBar(unittest.TestCase):
def test_rest_api_foo(self):
r = request("http://dummyurl")
# using a tuple
# `assertEqual` works as well, `assertTupleEqual` specifically
# highlights which elements that are different
self.assertTupleEqual(
(200, "hello world"),
(r.status_code, r.text),
)
# using a dict
# `assertEqual` works as well, `assertDictEqual` specifically
# highlights which elements that are different
self.assertDictEquals(
{'status': 200, 'text': "hello world"},
{'status': r.status_code, 'text': r.text},
)

您请求的内容不允许是有充分理由的。 如果您的测试可以在断言失败后继续,那么您很有可能会遇到不太明确的错误,因为环境处于意外状态。 考虑:

class TestContinuesOnAssert(unittest.TestCase):
def test_rest_api_foo(self):
"""Imagine this continues on assert"""
r = request("http://dummyurl")
self.assertIsNotNone(r)
self.assertEqual(r.status_code, 200)
self.assertEqual(r.text, "hello world")

在正常行为中,如果由于某种原因rNone您的代码会提前退出,并显示一条有用的消息:AssertionError: unexpectedly None. 没有它,您的代码将获得以下更不透明的异常:AttributeError: 'NoneType' object has no attribute 'status_code'.

最新更新