如何处理测试失败

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

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

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

pdb — Python 调试器 与 pytest 一起使用

在失败时转到 pdb

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

pytest --pdb

这将在每次失败(或键盘中断)时调用 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 命令)时,将恢复输出捕获。

使用内置断点函数

Python 3.7 引入了内置 breakpoint() 函数。Pytest 支持使用 breakpoint(),行为如下

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

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

  • --pdb 传递给 pytest 时,自定义内部 Pdb 跟踪 UI 将与 breakpoint() 和失败的测试/未处理的异常一起使用。

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

错误处理程序

在版本 5.0 中添加。

faulthandler 标准模块可用于在段错误或超时后转储 Python 追踪。

除非在命令行中给出了 -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 中引发但未处理的异常,导致线程不干净地终止。

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

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

可以使用 pytest.mark.filterwarnings 标记有选择地取消这些警告。警告类别是 pytest.PytestUnraisableExceptionWarningpytest.PytestUnhandledThreadExceptionWarning