如何重新运行失败的测试并在测试运行之间维护状态¶
用法¶
此插件提供了两个命令行选项,用于重新运行上次 pytest
调用中的失败项
--lf
、--last-failed
- 仅重新运行失败项。--ff
、--failed-first
- 先运行失败项,然后再运行其余测试。
对于清理(通常不需要),--cache-clear
选项允许在测试运行之前移除所有跨会话缓存内容。
其他插件可以访问 config.cache 对象,以便在 pytest
调用之间设置/获取json 可编码值。
注意
此插件默认启用,但可以在需要时禁用:请参阅 按名称停用/取消注册插件(此插件的内部名称为 cacheprovider
)。
仅重新运行失败项或先重新运行失败项¶
首先,让我们创建 50 个测试调用,其中只有 2 个失败
# content of test_50.py
import pytest
@pytest.mark.parametrize("i", range(50))
def test_num(i):
if i in (17, 25):
pytest.fail("bad luck")
如果您首次运行此测试,您将看到两个失败项
$ pytest -q
.................F.......F........................ [100%]
================================= FAILURES =================================
_______________________________ test_num[17] _______________________________
i = 17
@pytest.mark.parametrize("i", range(50))
def test_num(i):
if i in (17, 25):
> pytest.fail("bad luck")
E Failed: bad luck
test_50.py:7: Failed
_______________________________ test_num[25] _______________________________
i = 25
@pytest.mark.parametrize("i", range(50))
def test_num(i):
if i in (17, 25):
> pytest.fail("bad luck")
E Failed: bad luck
test_50.py:7: Failed
========================= short test summary info ==========================
FAILED test_50.py::test_num[17] - Failed: bad luck
FAILED test_50.py::test_num[25] - Failed: bad luck
2 failed, 48 passed in 0.12s
如果您随后使用 --lf
运行此测试
$ pytest --lf
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
collected 2 items
run-last-failure: rerun previous 2 failures
test_50.py FF [100%]
================================= FAILURES =================================
_______________________________ test_num[17] _______________________________
i = 17
@pytest.mark.parametrize("i", range(50))
def test_num(i):
if i in (17, 25):
> pytest.fail("bad luck")
E Failed: bad luck
test_50.py:7: Failed
_______________________________ test_num[25] _______________________________
i = 25
@pytest.mark.parametrize("i", range(50))
def test_num(i):
if i in (17, 25):
> pytest.fail("bad luck")
E Failed: bad luck
test_50.py:7: Failed
========================= short test summary info ==========================
FAILED test_50.py::test_num[17] - Failed: bad luck
FAILED test_50.py::test_num[25] - Failed: bad luck
============================ 2 failed in 0.12s =============================
您仅运行了上次运行中的两个失败测试,而 48 个通过测试未运行(“取消选择”)。
现在,如果您使用 --ff
选项运行,则将运行所有测试,但先执行之前的第一个失败项(可以从 FF
和点序列中看出)
$ pytest --ff
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
collected 50 items
run-last-failure: rerun previous 2 failures first
test_50.py FF................................................ [100%]
================================= FAILURES =================================
_______________________________ test_num[17] _______________________________
i = 17
@pytest.mark.parametrize("i", range(50))
def test_num(i):
if i in (17, 25):
> pytest.fail("bad luck")
E Failed: bad luck
test_50.py:7: Failed
_______________________________ test_num[25] _______________________________
i = 25
@pytest.mark.parametrize("i", range(50))
def test_num(i):
if i in (17, 25):
> pytest.fail("bad luck")
E Failed: bad luck
test_50.py:7: Failed
========================= short test summary info ==========================
FAILED test_50.py::test_num[17] - Failed: bad luck
FAILED test_50.py::test_num[25] - Failed: bad luck
======================= 2 failed, 48 passed in 0.12s =======================
新的 --nf
、--new-first
选项:先运行新测试,然后再运行其余测试,在这两种情况下,测试也会按文件修改时间进行排序,最近的文件排在前面。
上次运行中没有测试失败时的行为¶
--lfnf/--last-failed-no-failures
选项控制 --last-failed
的行为。确定在没有先前(已知)失败或未找到缓存的 lastfailed
数据时是否执行测试。
有两个选项
all
:当没有已知的测试失败时,运行所有测试(完整的测试套件)。这是默认设置。none
:当没有已知的测试失败时,仅发出一个消息,说明这一点,然后成功退出。
示例
pytest --last-failed --last-failed-no-failures all # runs the full test suite (default behavior)
pytest --last-failed --last-failed-no-failures none # runs no tests and exits successfully
新的 config.cache 对象¶
插件或 conftest.py 支持代码可以使用 pytest config
对象获取缓存值。这是一个基本示例插件,它实现了 fixture,该 fixture 在 pytest 调用之间重用先前创建的状态
# content of test_caching.py
import pytest
def expensive_computation():
print("running expensive computation...")
@pytest.fixture
def mydata(pytestconfig):
val = pytestconfig.cache.get("example/value", None)
if val is None:
expensive_computation()
val = 42
pytestconfig.cache.set("example/value", val)
return val
def test_function(mydata):
assert mydata == 23
如果您首次运行此命令,则可以看到打印语句
$ pytest -q
F [100%]
================================= FAILURES =================================
______________________________ test_function _______________________________
mydata = 42
def test_function(mydata):
> assert mydata == 23
E assert 42 == 23
test_caching.py:19: AssertionError
-------------------------- Captured stdout setup ---------------------------
running expensive computation...
========================= short test summary info ==========================
FAILED test_caching.py::test_function - assert 42 == 23
1 failed in 0.12s
如果您第二次运行它,则会从缓存中检索值,并且不会打印任何内容
$ pytest -q
F [100%]
================================= FAILURES =================================
______________________________ test_function _______________________________
mydata = 42
def test_function(mydata):
> assert mydata == 23
E assert 42 == 23
test_caching.py:19: AssertionError
========================= short test summary info ==========================
FAILED test_caching.py::test_function - assert 42 == 23
1 failed in 0.12s
有关更多详细信息,请参阅 config.cache fixture
。
检查缓存内容¶
您始终可以使用 --cache-show
命令行选项查看缓存的内容
$ pytest --cache-show
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
cachedir: /home/sweet/project/.pytest_cache
--------------------------- cache values for '*' ---------------------------
cache/lastfailed contains:
{'test_caching.py::test_function': True}
cache/nodeids contains:
['test_caching.py::test_function']
cache/stepwise contains:
[]
example/value contains:
42
========================== no tests ran in 0.12s ===========================
--cache-show
采用一个可选参数来指定用于过滤的 glob 模式
$ pytest --cache-show example/*
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
cachedir: /home/sweet/project/.pytest_cache
----------------------- cache values for 'example/*' -----------------------
example/value contains:
42
========================== no tests ran in 0.12s ===========================
清除缓存内容¶
您可以通过添加 --cache-clear
选项来指示 pytest 清除所有缓存文件和值,如下所示
pytest --cache-clear
建议在隔离和正确性比速度更重要的持续集成服务器中调用此选项。
逐步¶
作为 --lf -x
的替代方法,特别是对于您期望测试套件的大部分将失败的情况,--sw
,--stepwise
允许您一次修复它们。测试套件将运行到第一次失败,然后停止。在下次调用时,测试将从上次失败的测试继续,然后运行到下一个失败的测试。您可以使用 --stepwise-skip
选项忽略一个失败的测试,而是在第二个失败的测试上停止测试执行。如果您遇到失败的测试并且只想在稍后忽略它,这将非常有用。提供 --stepwise-skip
也将隐式启用 --stepwise
。