如何处理测试失败

在第一次(或 N 次)失败后停止

要在第一次 (N 次) 失败后停止测试过程

pytest -x           # stop after first failure
pytest --maxfail=2  # stop after two failures

在 pytest 中使用 pdb — Python 调试器

在失败时进入 pdb

Python 自带一个名为 pdb 的内置 Python 调试器。pytest 允许通过命令行选项进入 pdb 提示符。

pytest --pdb

这将在每次失败(或 KeyboardInterrupt)时调用 Python 调试器。通常你可能只想为第一次失败的测试执行此操作,以了解特定的失败情况。

pytest -x --pdb   # drop to PDB on first failure, then end test session
pytest --pdb --maxfail=3  # drop to PDB for first three failures

请注意,在任何失败情况下,异常信息都存储在 sys.last_valuesys.last_typesys.last_traceback 中。在交互式使用中,这允许使用任何调试工具进入事后调试。也可以手动访问异常信息,例如

>>> import sys
>>> sys.last_traceback.tb_lineno
42
>>> sys.last_value
AssertionError('assert result == "ok"',)

在测试开始时进入 pdb

pytest 允许通过命令行选项在每个测试开始时立即进入 pdb 提示符。

pytest --trace

这将在每个测试开始时调用 Python 调试器。

设置断点

要在代码中设置断点,请在代码中使用原生的 Python 调用 import pdb;pdb.set_trace(),pytest 将自动为该测试禁用其输出捕获。

  • 其他测试中的输出捕获不受影响。

  • 任何先前已捕获的测试输出都将照此处理。

  • 当结束调试器会话时(通过 continue 命令),输出捕获将恢复。

使用内置的 breakpoint 函数

Python 3.7 引入了一个内置的 breakpoint() 函数。Pytest 支持 breakpoint() 的以下行为:

  • 当调用 breakpoint() 并且 PYTHONBREAKPOINT 设置为默认值时,pytest 将使用自定义的内部 PDB 跟踪界面,而不是系统默认的 Pdb

  • 测试完成后,系统将默认恢复到系统 Pdb 跟踪界面。

  • --pdb 参数传递给 pytest 时,自定义的内部 Pdb 跟踪界面将同时用于 breakpoint() 和失败的测试/未处理的异常。

  • --pdbcls 可用于指定自定义调试器类。

故障处理程序

5.0 版本新增。

标准模块 faulthandler 可用于在段错误 (segfault) 或超时后转储 Python 追溯 (traceback)。

除非在命令行中给出 -p no:faulthandler,否则该模块在 pytest 运行中会自动启用。

此外,faulthandler_timeout=X 配置选项可用于在测试完成时间超过 X 秒时转储所有线程的追溯(Windows 上不可用)。

注意

此功能已从外部 pytest-faulthandler 插件中集成,有两个小差异:

  • 要禁用它,请使用 -p no:faulthandler 而不是 --no-faulthandler:前者可与任何插件一起使用,从而节省一个选项。

  • 命令行选项 --faulthandler-timeout 已变为 faulthandler_timeout 配置选项。它仍然可以通过命令行使用 -o faulthandler_timeout=X 进行配置。

关于无法引发的异常和未处理的线程异常的警告

6.2 版本新增。

未处理的异常是指在无法传播给调用者的情况下引发的异常。最常见的情况是在 __del__ 实现中引发的异常。

未处理的线程异常是指在 Thread 中引发但未处理的异常,导致线程不干净地终止。

这两种类型的异常通常被认为是 bug,但可能因为它们不会导致程序本身崩溃而未被注意到。Pytest 会检测这些情况并发出警告,该警告在测试运行摘要中可见。

除非在命令行中给出 -p no:unraisableexception(用于无法引发的异常)和 -p no:threadexception(用于线程异常)选项,否则插件会在 pytest 运行中自动启用。

可以使用 pytest.mark.filterwarnings 标记选择性地禁用这些警告。警告类别为 pytest.PytestUnraisableExceptionWarningpytest.PytestUnhandledThreadExceptionWarning