pytest 如何在第一项断言失败后不退出 for 循环
Posted
技术标签:
【中文标题】pytest 如何在第一项断言失败后不退出 for 循环【英文标题】:pytest how not to exit the for loop after first item assert fails 【发布时间】:2022-01-05 23:48:06 【问题描述】:我是 python 和 pytest 的新手。我正在尝试断言 2 个数据列表。由于列表中的第一个数据不匹配,因此断言在该点失败并且不继续进行下一项。但是我不希望我的执行停止,而是完成循环并捕获整体断言结果。有人可以帮我实现它吗?
代码
def test_compare_database():
records_src = [(1,James,smith,123),(2,Granpa,smith,124),(3,Linda,smith,123)]
records_trg = [(1,James,smith,111),(2,Granpa,ron,124),(3,Linda,smith,123)]
for a, b in zip(records_src, records_trg):
assert a == b
输出:列表比较中的第一项失败,这是正确的。但它止步于此。我希望整个 for 循环运行并捕获失败的结果。
============================= test session starts =============================
collecting ... collected 1 item
main_test.py::test_compare_database FAILED
def test_compare_database():
records_src = [(1,James,smith,123),(2,Granpa,smith,124),(3,Linda,smith,123)]
records_trg = [(1,James,smith,111),(2,Granpa,ron,124),(3,Linda,smith,123)]
for a, b in zip(records_src, records_trg):
> assert a == b
E AssertionError: assert (1,
'James',
'Smith',
123,)
!= (1,
'James',
'Smith',
111,)
【问题讨论】:
【参考方案1】:在 python 中使用“try”和“except”关键字允许错误不会干扰程序。这是你要找的吗?如果您想要的话,您还可以将我使用的“out”变量更改为列表变量。我希望这会有所帮助:)
James:int=1
smith:int=2
Granpa:int=3
Linda:int=4
ron:int=5
def test_compare_database()->str:
out:str=''
records_src = [(1,James,smith,123),(2,Granpa,smith,124),(3,Linda,smith,123)]
records_trg = [(1,James,smith,111),(2,Granpa,ron,124),(3,Linda,smith,123)]
for a, b in zip(records_src,records_trg):
try:
assert a==b
out+="success between "+str(a)+" and "+str(b)+'!'
except AssertionError as ae:
out+="there was an assertion error in the program between "+str(a)+" and "+str(b)+'!'
out+='\n'
return out
print(test_compare_database())
【讨论】:
【参考方案2】:您可以使用参数化测试根据数据创建多个测试,因此每对元组将在不同的测试中单独断言
def data_source():
records_src = [(1, 'James', 'smith', 123), (2, 'Granpa', 'smith', 124), (3, 'Linda', 'smith', 123)]
records_trg = [(1, 'James', 'smith', 111), (2, 'Granpa', 'ron', 124), (3, 'Linda', 'smith', 123)]
for a, b in zip(records_src, records_trg):
yield a, b
@pytest.mark.parametrize('a, b', data_source())
def test_compare_database(a, b):
assert a == b
控制台输出:
main_test.py::test_compare_database[a0-b0] FAILED [ 33%]
Tests\main_test.py:33 (test_compare_database[a0-b0])
(1, 'James', 'smith', 123) != (1, 'James', 'smith', 111)
Expected :(1, 'James', 'smith', 111)
Actual :(1, 'James', 'smith', 123)
<Click to see difference>
a = (1, 'James', 'smith', 123), b = (1, 'James', 'smith', 111)
@pytest.mark.parametrize('a, b', data_source())
def test_compare_database(a, b):
> assert a == b
E AssertionError: assert (1, 'James', 'smith', 123) == (1, 'James', 'smith', 111)
main_test.py:36: AssertionError
FAILED [ 66%]
Tests\main_test.py:33 (test_compare_database[a1-b1])
(2, 'Granpa', 'smith', 124) != (2, 'Granpa', 'ron', 124)
Expected :(2, 'Granpa', 'ron', 124)
Actual :(2, 'Granpa', 'smith', 124)
<Click to see difference>
a = (2, 'Granpa', 'smith', 124), b = (2, 'Granpa', 'ron', 124)
@pytest.mark.parametrize('a, b', data_source())
def test_compare_database(a, b):
> assert a == b
E AssertionError: assert (2, 'Granpa', 'smith', 124) == (2, 'Granpa', 'ron', 124)
main_test.py:36: AssertionError
PASSED [100%]
【讨论】:
谢谢你是个天才 嗨,这给了我循环中的所有结果。但是我看到了这样的错误“E _pytest.outcomes.XFailed: [NOTRUN] yield tests are removed in pytest 4.0 - test_compare_database will be忽略” @EverydayLearner 更新你的 pytest 版本。以上是关于pytest 如何在第一项断言失败后不退出 for 循环的主要内容,如果未能解决你的问题,请参考以下文章
pytest文档36-断言失败后还能继续执行pytest-assume