ITADN
pytest-dev/pytest-rerunfailures
README.md
以下内容由 AI 翻译,如有问题请点此提交 issue 反馈

pytest-rerunfailures

.. START-SHORT-DESCRIPTION

pytest-rerunfailures 是一个 pytest <https://pytest.org>_ 插件, 用于重新运行测试以消除间歇性失败。

.. END-SHORT-DESCRIPTION

.. image:: https://img.shields.io/badge/license-MPL%202.0-blue.svg :target: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/LICENSE :alt: License .. image:: https://img.shields.io/pypi/v/pytest-rerunfailures.svg :target: https://pypi.python.org/pypi/pytest-rerunfailures/ :alt: PyPI .. image:: https://github.com/pytest-dev/pytest-rerunfailures/workflows/Test/badge.svg :target: https://github.com/pytest-dev/pytest-rerunfailures/actions :alt: GitHub Actions .. image:: https://readthedocs.org/projects/pytest-rerunfailures/badge/?version=latest :target: https://pytest-rerunfailures.readthedocs.io/latest/?badge=latest :alt: Documentation Status

.. START-INSTALLATION

Requirements

要使用 pytest-rerunfailures,您需要满足以下先决条件:

  • Python 3.10+ 或 PyPy3
  • pytest 8.2 或更高版本

该插件可以在满足以下可选 先决条件的情况下从严重崩溃中恢复:

  • pytest-xdist 2.3.0 或更高版本

当前该包针对最近 5 个次要版本的 pytest 进行了测试。如果 您使用的是旧版本的 pytest,应考虑更新或 使用该包的较早版本。

Installation

要安装 pytest-rerunfailures:

.. code-block:: bash

$ pip install pytest-rerunfailures

.. END-INSTALLATION

从严重崩溃中恢复

如果一个或多个测试触发了严重崩溃(例如:段错误),此插件通常将无法重新运行该测试。但是,如果安装了兼容版本的 pytest-xdist,并且测试在 pytest-xdist 中使用 -n 标志运行,则此插件将能够重新运行崩溃的测试,前提是 worker 和 controller 位于同一局域网(由于大多数情况下 worker 和 controller 位于同一台计算机上,因此这一假设在几乎所有情况下都成立)。 如果该假设不成立,则此功能可能无法正常工作。

重新运行所有失败

要重新运行所有测试失败,请使用 --reruns 命令行选项,并指定 您希望测试运行的最大次数:

.. code-block:: bash

$ pytest --reruns 5

失败的 fixture 或 setup_class 也将被重新执行。

要在重新运行之间添加延迟时间,请使用 --reruns-delay 命令行 选项,并指定在启动下一次 测试重新运行之前希望等待的秒数:

.. code-block:: bash

$ pytest --reruns 5 --reruns-delay 1

要在每次尝试后增加延迟(指数退避),请使用 --reruns-delay-backoff-factor 选项。第 n 次重新运行前的延迟为 reruns_delay * reruns_delay_backoff_factor ** (n - 1)。默认因子为 1.0,这将保持延迟恒定。例如,以下示例在三次重新运行前分别等待 1、2 和 4 秒:

.. code-block:: bash

$ pytest --reruns 3 --reruns-delay 1 --reruns-delay-backoff-factor 2

重新运行匹配特定表达式的所有失败

要仅重新运行匹配特定表达式列表的失败,请使用 --only-rerun 标志并传入一个正则表达式。例如, 以下命令将仅重新运行匹配 AssertionError 的错误:

.. code-block:: bash

$ pytest --reruns 5 --only-rerun AssertionError

多次传递该标志会累积参数,因此以下命令 将仅重新运行匹配 AssertionError or ValueError 的错误:

.. code-block:: bash

$ pytest --reruns 5 --only-rerun AssertionError --only-rerun ValueError

重新运行除匹配特定表达式外的所有失败

要仅重新运行不匹配特定表达式列表的失败,请使用 --rerun-except 标志并传入一个正则表达式。例如, 以下命令将仅重新运行不匹配 AssertionError 的错误:

.. code-block:: bash

$ pytest --reruns 5 --rerun-except AssertionError

多次传递该标志会累积参数,因此以下命令 将仅重新运行不匹配 AssertionError or OSError 的错误:

.. code-block:: bash

$ pytest --reruns 5 --rerun-except AssertionError --rerun-except OSError

重新运行单个失败

要将单个测试标记为不稳定(flaky),并在其失败时自动重新运行,请添加 flaky 标记,并指定你希望测试运行的最大次数:

.. code-block:: python

@pytest.mark.flaky(reruns=5) def test_example(): import random assert random.choice([True, False])

请注意,当 teardown 失败时,会为该用例生成两个报告,一个针对测试用例,另一个针对 teardown 错误。

你还可以在标记中指定重新运行的延迟时间,以及用于指数退避的退避因子:

.. code-block:: python

@pytest.mark.flaky(reruns=5, reruns_delay=2) def test_example(): import random assert random.choice([True, False])

.. code-block:: python

@pytest.mark.flaky(reruns=5, reruns_delay=2, reruns_delay_backoff_factor=2) def test_example(): import random assert random.choice([True, False])

你还可以在重新运行标记中指定一个可选的 condition

.. code-block:: python

@pytest.mark.flaky(reruns=5, condition=sys.platform.startswith("win32")) def test_example(): import random assert random.choice([True, False])

可以通过分别为 only_rerun and rerun_except. They override the --only-rerun--rerun-except 命令行参数指定正则表达式来实现异常过滤。

参数可以是单个字符串:

.. code-block:: python

@pytest.mark.flaky(rerun_except="AssertionError") def test_example(): raise AssertionError()

或者是一个字符串列表:

.. code-block:: python

@pytest.mark.flaky(only_rerun=["AssertionError", "ValueError"]) def test_example(): raise AssertionError()

异常类也被接受,并匹配任何子类:

.. code-block:: python

@pytest.mark.flaky(only_rerun=[AssertionError, ValueError]) def test_example(): raise AssertionError()

你可以使用 @pytest.mark.flaky(condition) similarly as @pytest.mark.skipif(condition), see pytest-mark-skipif <https://docs.pytest.org/en/6.2.x/reference.html#pytest-mark-skipif>_

.. code-block:: python

@pytest.mark.flaky(reruns=2,condition="sys.platform.startswith('win32')")
def test_example():
    import random
    assert random.choice([True, False])
# totally same as the above
@pytest.mark.flaky(reruns=2,condition=sys.platform.startswith("win32"))
def test_example():
  import random
  assert random.choice([True, False])

请注意,对于任何为真值的 condition,测试都将重新运行。

强制重新运行次数

要全局强制特定的重新运行次数,而不管测试标记中指定的重新运行次数,请传递 --force-reruns

.. code-block:: bash

$ pytest --force-reruns 5

重新运行模式

默认情况下,标记中的计数严格优先于全局 --reruns 设置。若要使其变为累加,请传递 --reruns-mode=append。使用 append, a test decorated with @pytest.mark.flaky(reruns=2) 运行 --reruns 4 will be re-run up to `` 次:

.. code-block:: bash

$ pytest --reruns 4 --reruns-mode append

限制整个测试套件的总重新运行次数

为了限制整个测试套件中重跑的总次数,无论有多少个单独的测试失败,请传入 --max-suite-reruns。一旦达到该限制,即使单独的测试仍有剩余的重跑次数,也不会再进行任何重跑:

.. code-block:: bash

$ pytest --reruns 3 --max-suite-reruns 10

这在大型测试套件中非常有用,可以在许多测试同时不稳定时限制资源使用。该上限在重跑选择之后应用,包括配置了 --force-reruns and @pytest.mark.flaky 的测试。

显示重试失败的 traceback

默认情况下,只有不稳定测试的最终尝试会产生 traceback,因此来自早期尝试的失败(包括那些在重跑后最终通过的测试)会被静默丢弃。若要检查它们,请传入 --rerun-show-tracebacks

.. code-block:: bash

$ pytest --reruns 2 --rerun-show-tracebacks

每次重试尝试的 traceback 都会追加到 rerun test summary info 部分。当设置该标志时,该部分会自动输出, 因此不需要 -rR

输出

以下是插件在运行 --reruns 2 and -r aR 时提供的输出示例::

test_report.py RRF

================================== FAILURES ================================== __________________________________ test_fail _________________________________

  def test_fail():
  assert False

E assert False

test_report.py:9: AssertionError ============================ 重跑测试摘要信息 ========================= 重跑 test_report.py::test_fail 重跑 test_report.py::test_fail ============================ 简短测试摘要信息 ========================= 失败 test_report.py::test_fail ======================= 1 个失败, 2 次重跑, 耗时 0.02 秒 ====================

注意,输出将显示所有重跑。在所有重跑中均失败的测试 将被标记为失败。

.. START-COMPATIBILITY

兼容性

  • 此插件与 pytest-xdist 的 --looponfail 标志兼容。
  • 此插件与核心 --pdb 标志兼容。
  • 此插件与插件 flaky <https://pypi.org/project/flaky/>_ 不兼容,你只能拥有 pytest-rerunfailures or flaky,而不能同时拥有两者。

.. END-COMPATIBILITY

.. START-PRIORITY

优先级

你可以在三个地方指定参数。因此,如果你在全部三个地方都设置了重跑次数, 哪一个具有优先级?

  • 最高优先级是标记,例如 @pytest.mark.flaky(reruns=1)
  • 第二优先级是命令行上指定的内容,例如 --reruns=2
  • 最低优先级是 pyproject.toml (or pytest.ini) file setting, like reruns = 3

此外,通过在命令行上传递 --force-reruns 参数, 可以覆盖上述三者。传递 --reruns-mode=append 会使标记计数和 全局 --reruns / reruns ini 设置变为累加而非严格模式。

.. END-PRIORITY

.. START-CONTRIBUTING

资源

  • Issue Tracker <https://github.com/pytest-dev/pytest-rerunfailures/issues>_
  • Code <https://github.com/pytest-dev/pytest-rerunfailures/>_

Development

  • 测试执行次数可从测试 item 对象的 execution_count 属性中获取。示例:

    .. code-block:: python

    @hookimpl(tryfirst=True) def pytest_runtest_makereport(item, call): print(item.execution_count)

.. END-CONTRIBUTING