在单元测试python中的失败步骤中运行测试用例
我有一个Python测试套件,其中有几个使用单元测试框架的测试用例。我使用的是导入单元测试 若测试用例中的一个测试步骤失败,测试用例将转到teardown类。即使有一个测试用例失败,我也希望继续测试用例的其余部分 单元测试的默认行为:如果任何测试步骤失败,它将分解类并结束测试用例在单元测试python中的失败步骤中运行测试用例,python,python-unittest,Python,Python Unittest,我有一个Python测试套件,其中有几个使用单元测试框架的测试用例。我使用的是导入单元测试 若测试用例中的一个测试步骤失败,测试用例将转到teardown类。即使有一个测试用例失败,我也希望继续测试用例的其余部分 单元测试的默认行为:如果任何测试步骤失败,它将分解类并结束测试用例 测试步骤:我的意思是断言相等,就像这个内置过程,它定义了是失败还是通过 class TestFoo(unittest.TestCase): def test_case_1(self): self
测试步骤:我的意思是断言相等,就像这个内置过程,它定义了是失败还是通过
class TestFoo(unittest.TestCase):
def test_case_1(self):
self.assertEqual(1, 2)
self.assertEqual(1, 3)
self.assertEqual(1, 1)
AssertionError: Tuples differ: (1, 1, 1) != (2, 3, 1)
First differing element 0:
1
2
- (1, 1, 1)
? ^ ^
+ (2, 3, 1)
? ^ ^
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")
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")
第一个断言将失败,下面的断言将不运行,但测试将结束,并将调用self.tearDown方法
当你断言的时候,你的意思是这个条件是绝对正确的,或者继续下去没有意义。你的意思是:“如果一个不等于两个,那么生活就没有意义了……”
大多数时候都是这样。例如,如果结果代码不是预期的,则不希望检查RESTAPI的结果体
您应在一个步骤中测试所有等式,以确保它们都将被检查。可以将它们分组为元组,例如:
class TestFoo(unittest.TestCase):
def test_case_1(self):
self.assertEqual((1, 1, 1), (2, 3, 1))
然后您将得到如下输出:
class TestFoo(unittest.TestCase):
def test_case_1(self):
self.assertEqual(1, 2)
self.assertEqual(1, 3)
self.assertEqual(1, 1)
AssertionError: Tuples differ: (1, 1, 1) != (2, 3, 1)
First differing element 0:
1
2
- (1, 1, 1)
? ^ ^
+ (2, 3, 1)
? ^ ^
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")
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")
从python文档中:
assertEqual(第一,第二,msg=None)
测试第一个和第二个是否相等。如果两个值不相等,
测试将失败
此外,如果第一个和第二个是完全相同的类型,并且
list、tuple、dict、set、frozenset或str或子类所包含的任何类型
使用addTypeEqualityFunc()注册特定于类型的等式
函数将被调用以生成更有用的默认值
错误消息(另请参阅类型特定方法列表)
[编辑]——在对这个问题进行了一些澄清之后,对其本身进行了评论,但还没有一个代码示例
考虑到你有一些不同的东西,比如:
class TestFoo(unittest.TestCase):
def test_case_1(self):
self.assertEqual(1, 2)
self.assertEqual(1, 3)
self.assertEqual(1, 1)
AssertionError: Tuples differ: (1, 1, 1) != (2, 3, 1)
First differing element 0:
1
2
- (1, 1, 1)
? ^ ^
+ (2, 3, 1)
? ^ ^
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")
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")
你可以做很多(骇客的)事情,比如计算失败次数,而不是在最后断言和断言计数器值:
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)
或者创建一个helper函数来断言、记录、计数和吞咽异常,然后在最后断言计数器。有很多可能性
然而,一般来说,最好的(最简单、清晰、枯燥的)方式是评论中已经提出的方式:
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)
我肯定我没有涵盖你实际问题的所有可能性,但这可能有助于说明你的开放式问题有多少可能性。所以,请澄清您的问题。子测试如何
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 TestFoo(unittest.TestCase):
def test_case_1(self):
self.assertEqual(1, 2)
self.assertEqual(1, 3)
self.assertEqual(1, 1)
AssertionError: Tuples differ: (1, 1, 1) != (2, 3, 1)
First differing element 0:
1
2
- (1, 1, 1)
? ^ ^
+ (2, 3, 1)
? ^ ^
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")
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
中失败时(或者,一个常见的Python测试框架),没有一种内置的方法可以继续
实现相同效果的最惯用方法是使用同时比较dict或tuple值
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")
对于正常行为,如果出于某种原因
r
为None
您的代码会提前退出,并显示一条有用的消息:AssertionError:意外无
。如果没有它,您的代码将得到以下更不透明的异常:AttributeError:'NoneType'对象没有属性“status\u code”
它总是在其他测试中继续。我不知道你为什么会有不同的体验。你能提供你的测试代码吗?这会让你的问题更容易回答。我不确定我是否完全理解你的问题,因为我总是让我的测试继续进行,即使测试失败。我从来没有遇到过这样的问题。考虑到已经有几个答案了,也许我遗漏了一个我不理解的关键部分?除非您在一个测试方法中引用多个断言?我明白您的意思,但是在编写测试用例时,有很多测试步骤。有时我们不希望在失败的步骤停止,而是希望测试继续并打印失败的消息。这意味着您在一个测试中测试多个内容。不要这样做。在一个测试中,测试到第一个故障点,以确保其正常工作。在另一个测试中,运行相同的设置,但不要检查该故障(另一个测试正在处理该故障),而是检查下一个故障。等等这也可能是您正在测试的函数太大的证据。如果是这种情况,Nitesh就好像Adam已经回答过:只需将测试用例分成多个步骤。此外,如果我没有理解你的观点,那么请澄清你的问题,并添加已经询问过的示例。看来亚当·巴恩斯应该被接受。看起来亚当·巴恩斯的评论应该是公认的答案,现在尼特什在这些评论中对问题做了一些澄清。尽管它没有做到问题所要求的(这一点无论如何都不清楚),亚当·巴恩斯的评论是最好的方法,这就是最佳实践应该做的事情,这取决于你的案例,是非常有趣的。具体来说,对于url请求测试,我会在一个测试用例中保持简单,如果代码错误,就不检查文本。当然,这是一个有效的例子。