pytest 核心功能-重新运行失败的测试并在测试运行之间保持状态

2022-03-21 11:28 更新

用法

该插件提供了两个命令行选项来重新运行上次 pytest 调用的失败:

  • --lf​, ​--last-failed​ - 只重新运行失败。
  • --ff​, ​--failed-first​ - 先运行失败,然后运行其余测试。

对于清理(通常不需要), ​--cache-clear​ 选项允许在测试运行之前删除所有跨会话缓存内容。

其他插件可以访问 ​config.cache​ 对象以在 pytest 调用之间设置/获取 ​json可编码值。

只重新运行失败或先运行失败

首先,我们创建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-7.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​ 选项运行,所有测试都将运行,但之前的第一个失败将首先执行:

$ pytest --ff
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-7.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​ 选项:首先运行新测试,然后是其余测试,在这两种情况下,测试也按文件修改时间排序,最近的文件首先出现。

上次运行中没有测试失败时的行为

如果在上次运行中没有测试失败,或者没有找到缓存的 lastfailed 数据,则可以使用 --last-failed-no-failures 选项将 pytest 配置为运行所有测试或不运行测试,该选项采用以下选项之一 :

pytest --last-failed --last-failed-no-failures all    # run all tests (default behavior)
pytest --last-failed --last-failed-no-failures none   # run no tests and exit

新的 config.cache 对象

插件或 ​conftest.py​ 支持代码可以使用 pytest 配置对象获取缓存值。 这是一个基本示例插件,它实现了一个在 pytest 调用中重用先前创建的状态的​fixture​:

# content of test_caching.py
import pytest
import time


def expensive_computation():
    print("running expensive computation...")


@pytest.fixture
def mydata(request):
    val = request.config.cache.get("example/value", None)
    if val is None:
        expensive_computation()
        val = 42
        request.config.cache.set("example/value", val)
    return val


def test_function(mydata):
    assert mydata == 23

如果你是第一次运行这个命令,你可以看到 ​print语句:

$ pytest -q
F                                                                    [100%]
================================= FAILURES =================================
______________________________ test_function _______________________________

mydata = 42

    def test_function(mydata):
>       assert mydata == 23
E       assert 42 == 23

test_caching.py:20: 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:20: AssertionError
========================= short test summary info ==========================
FAILED test_caching.py::test_function - assert 42 == 23
1 failed in 0.12s

检查缓存内容

您始终可以使用 ​--cache-show​ 命令行选项查看缓存的内容:

$ pytest --cache-show
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-7.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​ 采用可选参数来指定用于过滤的全局模式:

$ pytest --cache-show example/*
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-7.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

对于来自持续集成服务器的调用,建议这样做,因为隔离和正确性比速度更重要。

Stepwise

作为 ​--lf -x​ 的替代方案,特别是对于您预计大部分测试套件将失败的情况,​--sw​, ​--stepwise​ 允许您一次修复一个。 测试套件将一直运行到第一次失败,然后停止。 在下一次调用时,测试将从上一个失败的测试继续,然后运行直到下一个失败的测试。 您可以使用 ​--stepwise-skip​ 选项忽略一个失败的测试并在第二个失败的测试上停止测试执行。 如果您陷入失败的测试并且只想在以后忽略它,这很有用。 提供 ​--stepwise-skip​ 也将隐式启用 ​--stepwise


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号