即使其中一些失败,如何运行所有 PyTest 断言?
Posted
技术标签:
【中文标题】即使其中一些失败,如何运行所有 PyTest 断言?【英文标题】:How to run all PyTest assertions even if some of them fail? 【发布时间】:2016-04-20 16:25:03 【问题描述】:我正在寻找一种方法来运行我在 PyTest 中的单元测试中的所有断言,即使其中一些失败。我知道必须有一个简单的方法来做到这一点。我检查了 CLI 选项并浏览了该站点以查找类似的问题/答案,但没有看到任何内容。对不起,如果这已经回答了。
例如,考虑以下代码 sn-p,旁边有 PyTest 代码:
def parrot(i):
return i
def test_parrot():
assert parrot(0) == 0
assert parrot(1) == 1
assert parrot(2) == 1
assert parrot(2) == 2
默认情况下,第一次失败就停止执行:
$ python -m pytest fail_me.py
=================== test session starts ===================
platform linux2 -- Python 2.7.10, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
rootdir: /home/npsrt/Documents/repo/codewars, inifile:
collected 1 items
fail_me.py F
=================== FAILURES ===================
___________________ test_parrot ___________________
def test_parrot():
assert parrot(0) == 0
assert parrot(1) == 1
> assert parrot(2) == 1
E assert 2 == 1
E + where 2 = parrot(2)
fail_me.py:7: AssertionError
=================== 1 failed in 0.05 seconds ===================
我想做的是让代码在 PyTest 遇到第一次失败后继续执行。
【问题讨论】:
另见this questionunittest
,由一堆非常相似的问题链接到
@pytest.mark.parametrize
是您正在寻找的。它需要 2 个参数,将提供数据的变量名称,以及您希望提供给测试的数据。因此,要实现您想要的,可以执行以下操作。 @pytest.mark.parametrize('parrot_num', (1, 2, 3, 4, 5)) def parrot(parrot_num): return parrot_num def test_parrot(): assert parrot(0) == 0 assert parrot(1) = = 1 断言鹦鹉(2) == 1 断言鹦鹉(2) == 2
【参考方案1】:
正如其他人已经提到的,理想情况下,您应该编写多个测试,并且每个测试只有一个断言(这不是硬性限制,而是一个很好的指导方针)。
@pytest.mark.parametrize
装饰器让这一切变得简单:
import pytest
def parrot(i):
return i
@pytest.mark.parametrize('inp, expected', [(0, 0), (1, 1), (2, 1), (2, 2)])
def test_parrot(inp, expected):
assert parrot(inp) == expected
使用-v
运行时:
parrot.py::test_parrot[0-0] PASSED
parrot.py::test_parrot[1-1] PASSED
parrot.py::test_parrot[2-1] FAILED
parrot.py::test_parrot[2-2] PASSED
=================================== FAILURES ===================================
_______________________________ test_parrot[2-1] _______________________________
inp = 2, expected = 1
@pytest.mark.parametrize('inp, expected', [(0, 0), (1, 1), (2, 1), (2, 2)])
def test_parrot(inp, expected):
> assert parrot(inp) == expected
E assert 2 == 1
E + where 2 = parrot(2)
parrot.py:8: AssertionError
====================== 1 failed, 3 passed in 0.01 seconds ======================
【讨论】:
谢谢,我会调查一下【参考方案2】:它运行了你所有的测试。您只编写了一个测试,并且该测试运行了!
如果您想要非致命断言,如果断言失败,测试将继续进行(如 Google Test 的 EXPECT 宏),请尝试提供该功能的 pytest-expect。这是他们网站给出的例子:
def test_func(expect):
expect('a' == 'b')
expect(1 != 1)
a = 1
b = 2
expect(a == b, 'a:%s b:%s' % (a,b))
您可以看到期望失败不会停止测试,并且会报告所有失败的期望:
$ python -m pytest test_expect.py
================ test session starts =================
platform darwin -- Python 2.7.9 -- py-1.4.26 -- pytest-2.7.0
rootdir: /Users/okken/example, inifile:
plugins: expect
collected 1 items
test_expect.py F
====================== FAILURES ======================
_____________________ test_func ______________________
> expect('a' == 'b')
test_expect.py:2
--------
> expect(1 != 1)
test_expect.py:3
--------
> expect(a == b, 'a:%s b:%s' % (a,b))
a:1 b:2
test_expect.py:6
--------
Failed Expectations:3
============== 1 failed in 0.01 seconds ==============
【讨论】:
啊哈!这回答了我的问题。我只是在运行一个测试,其中包含多个断言。我也会检查 pytest-expect 模块。 请注意,development onpytest-expect
已经过时了
关于pytest-check
的答案见下文,这是pytest-expect
的重写【参考方案3】:
pytest 插件 pytest-check 是对 pytest-expect 的重写(之前在这里推荐过,但已经过时了)。它会让你像这样做一个“软”断言:
来自 GitHub 存储库的示例:
import pytest_check as check
def test_example():
a = 1
b = 2
c = [2, 4, 6]
check.greater(a, b)
check.less_equal(b, a)
check.is_in(a, c, "Is 1 in the list")
check.is_not_in(b, c, "make sure 2 isn't in list")
【讨论】:
【参考方案4】:您应该可以使用--maxfail
参数来控制它。我相信默认设置是不会因为失败而停止,所以我会检查你可能拥有的任何 py.test 配置文件,以寻找覆盖它的地方。
【讨论】:
感谢您的快速回复。 (有关我的环境的信息,请参阅上面我更新的原始问题。)不幸的是,它似乎对我不起作用。当我调用 --maxfail 时,PyTest 给了我相同的输出,就像我在没有它的情况下运行时一样。我的新命令行是:python -m pytest --maxfail=5 fail_me.py--maxfail
确定失败的 测试 数量,而不是 assert
ions 的数量
默认确实是不停止。请注意--maxfail=1
的别名是--exitfirst
或-x
,也可以显示pytest
文件,例如:addopts = -x
以上是关于即使其中一些失败,如何运行所有 PyTest 断言?的主要内容,如果未能解决你的问题,请参考以下文章
pytest文档36-断言失败后还能继续执行pytest-assume