pytest 3.7.3 版本发布详解:8 项缺陷修复、teardown 捕获行为回归与采集逻辑修正
pytest 3.7.3 版本发布详解8 项缺陷修复、teardown 捕获行为回归与采集逻辑修正【免费下载链接】pytestThe pytest framework makes it easy to write small tests, yet scales to support complex functional testing项目地址: https://gitcode.com/GitHub_Trending/py/pytest本文基于 pytest 官方发布公告 doc/en/announce/release-3.7.3.rst 撰写系统梳理 pytest 3.7.3 这一 bug-fix 版本的修复全景。读者可以了解到该版本为何被称为drop-in replacement、如何安全升级以及 8 项缺陷修复背后涉及的捕获机制、采集逻辑与 doctest 工作流的源码级原理从而在升级后准确预判行为变化。版本概况一次纯缺陷修复的补丁版本pytest 3.7.3 于 2018-08-26 发布到 PyPI见 doc/en/changelog.rst 中 pytest 3.7.3 (2018-08-26) 一节。官方发布公告明确将其定性为bug-fix release缺陷修复版本同时强调它是一个drop-in replacement直接替换版本——即 API 与既有行为保持兼容现有测试项目无需改动即可无缝升级。作为补丁版本3.7.3 的修复全部聚焦于 3.7 系列引入的回归问题与采集边界场景共包含8 项缺陷修复、3 项文档改进、2 项内部变更未引入任何新特性feature或破坏性变更breaking change。这也解释了为什么发布公告的正文极短它的核心信息就是这是一个可以放心原地替换的稳定补丁。升级方式一条命令完成替换发布公告给出了唯一的官方升级方式pip install --upgrade pytest由于 3.7.3 是 drop-in replacement升级不需要修改任何测试代码、配置或 conftest.py。升级后可通过以下命令确认版本pytest --version在 pyproject.toml 中可以查看当前仓库的版本声明在 doc/en/announce/index.rst 中可以看到该版本发布公告在全部历史公告中的索引位置。缺陷修复详解8 个修复点与源码依据本节按 doc/en/changelog.rst 的记录逐项展开并补充当前仓库中对应的源码实现证据。1. teardown 阶段恢复使用 capsys / capfd 检查输出issue #3033Fixtures during teardown can again usecapsysandcapfdto inspect output captured during tests.这是 3.7.3 中最重要的一项修复解决了 3.7.0 引入的回归在 fixture 的 teardown 阶段yield 之后的部分capsys与capfd再次可以读取测试执行期间捕获的输出。在源码层面capsys、capfd等捕获相关 fixture 定义在 src/_pytest/capture.py 中capsys捕获sys.stdout/sys.stderr文本输出src/_pytest/capture.py#L1013capsysbinary捕获字节输出src/_pytest/capture.py#L1076capfd捕获操作系统级别的文件描述符 1/2src/_pytest/capture.py#L1104capfdbinary文件描述符级别的字节输出src/_pytest/capture.py#L1132。修复涉及全局捕获状态的恢复逻辑。在 src/_pytest/capture.py#L788-L796 中可以看到resume_global_capture()与suspend_global_capture()的实现它们负责在 fixture 局部捕获与全局捕获之间切换时挂起/恢复全局捕获状态。3.7.3 的修复确保 teardown 执行期间全局捕获能被正确恢复从而让 teardown 中的capsys.readouterr()能拿到测试体内产生的输出。一个典型的验证场景如下import pytest pytest.fixture def check_output(capsys): yield captured capsys.readouterr() assert hello in captured.out # 3.7.3 之前此处可能拿到空输出 def test_emit(check_output): print(hello from test body)2. 匹配 python_files 配置的init.py 文件可被正常采集issue #3773Fix collection of tests from__init__.pyfiles if they match thepython_filesconfiguration option.此前若用户在python_files中配置了能匹配__init__.py的模式从包内__init__.py采集测试会失败3.7.3 修复了这一场景。python_files是 Python 测试模块发现的 glob 模式配置定义在 src/_pytest/python.py#L96-L103默认值为[test_*.py, *_test.py]。用户可以这样扩展# pytest.ini [pytest] python_files test_*.py *_test.py __init__.py与之配套的python_classes与python_functions也在同一注册块中src/_pytest/python.py#L104-L115默认分别为[Test]前缀与[test]前缀。3.7.3 修复后__init__.py中定义的测试类与测试函数能够按这些规则被正常收集这一行为与包初始化文件同时承载测试用例的工程实践例如在包的__init__.py中编写冒烟测试相兼容。3. 连续子包的 fixture teardown 不再被推迟到外层包末尾issue #3796Fix issue where teardown of fixtures of consecutive sub-packages were executed once, at the end of the outer package.这是一个采集/执行顺序回归当多个连续的子包sub-package各自声明了 scope 化的 fixture 时旧版本会把它们的 teardown 错误地合并延迟到外层包全部执行完毕后才运行一次导致每个子包实际只得到一次 teardown 机会。3.7.3 修正了包收集树的清理时机使每个子包的 fixture teardown 按正确的 scope 边界及时执行。从源码结构看包的收集由Package收集器完成它专用于包含__init__.py的目录而普通目录由Dir收集器处理二者的职责划分说明见 src/_pytest/python.py#L660-L667。修复确保嵌套包边界上的节点回收finalization不会跨越子包边界被错误合并。4. --show-captureno 不再漏出 teardown 期间的日志issue #3816Fix bug where--show-capturenooption would still show logs printed during fixture teardown.--show-capture选项控制测试失败时是否在报告中展示捕获到的输出。3.7.3 之前即使指定--show-capturenofixture teardown 阶段打印的日志仍可能出现在失败报告中。修复后该选项对 teardown 阶段产生的日志同样生效pytest --show-captureno这与第 1 项修复同属teardown 阶段捕获状态回归的连锁修正一旦 teardown 期间捕获恢复正常报告阶段的展示开关也必须同时作用于此阶段的输出。5. 实时 CLI 日志开启时 stdout/stderr 仍可被捕获issue #3819Fixstdout/stderrnot getting captured when real-time cli logging is active.pytest 的日志插件logging在启用实时输出live logging时会破坏 stdout/stderr 的捕获链路。3.7.3 修复了该场景使测试与 fixture 中的输出在启用实时日志时依然能被capsys等机制捕获而不是直接穿透到终端。相关捕获基础设施同样位于 src/_pytest/capture.py。6. --doctest-modules 与命令行节点 ID 语法冲突issue #3843Fix collection error when specifying test functions directly in the command line usingtest.py::testsyntax together with--doctest-modules.当用户在命令行直接以test.py::test的节点 IDnodeid语法指定测试函数同时又开启--doctest-modules时旧版本会抛出采集错误。--doctest-modules选项注册于 src/_pytest/doctest.py#L82-L86其语义是对所有 .py 模块运行 doctest。3.7.3 修正了模块级 doctest 采集器与显式节点 ID 定位逻辑之间的冲突修复后以下命令可以正常工作pytest --doctest-modules tests/test_foo.py::test_bar7. Python 2 下 testdir.runpytest 支持 Unicode 参数issue #3848Fix bugs where unicode arguments could not be passed totestdir.runpyteston Python 2.这是一个兼容性修复在 Python 2 环境中向testdir.runpytestpytester插件提供用于在测试中运行 pytest 子进程传递 Unicode 参数会出错3.7.3 修复了该问题。pytester是 pytest 自带的测试夹具平台其实现位于 src/_pytest/pytester.py。当前仓库中的测试套件大量依赖它例如 testing/acceptance_test.py 中各类端到端断言均通过pytester运行真实的 pytest 进程。8. 大写字母开头的包内文件名不再被重复采集issue #3854Fix double collection of tests within packages when the filename starts with a capital letter.当包内测试文件名以大写字母开头时例如TestHelpers.py或Foo_test.py旧版本会在包内被采集两次导致测试重复执行。3.7.3 修复了包目录扫描pytest_collect_directory见 src/_pytest/python.py#L201-L207与文件级采集之间的去重逻辑。这个修复与python_files配置的 glob 匹配行为src/_pytest/python.py#L406-L412 的startswith/fnmatch匹配路径紧密相关确保大小写敏感的匹配不会造成同一文件的重复收集。文档改进3.7.3 同步修复了三处文档问题issue #3824为python_files增加了多个 glob 模式同时匹配的示例。如上文所示python_files支持配置多个模式如test_*.py *_test.py文档补充了该能力的完整示例方便使用者正确组合匹配规则。issue #3833补齐了pytester.Testdir缺失的 API 文档。pytester是测试 pytest 自身的核心工具其文档完整性直接影响插件作者编写集成测试。issue #3870修正 setuptools 集成的文档说明使通过entry_points注册插件/测试用例的指引与真实行为一致。内部变更Trivial/Internal Changesissue #3826将失效的类型注解type annotations替换为类型注释type comments。pytest 在 Python 2/3 双兼容时期选择 type comments 以保证旧解释器不因注解语法报错这是当时兼容性策略的体现。issue #3845从文档中移除对 issue #568 的引用因为该问题在此前版本已修复保留引用会造成误导。升级建议与行为预期综合 8 项修复可以发现3.7.3 的核心价值集中在两个区域捕获机制capture回归修复#3033、#3816、#3819如果你在 fixture teardown 中依赖capsys/capfd检查测试输出或使用--show-captureno与实时日志升级到 3.7.3 后行为会恢复正确采集逻辑collection边界修复#3773、#3796、#3843、#3854涉及python_files自定义、多级包 fixture 作用域、--doctest-modules组合使用、大写文件名等场景升级后重复采集与采集报错问题将消失。由于该版本不含新特性与破坏性变更执行pip install --upgrade pytest即可平滑升级。若升级后仍需追溯具体行为差异可直接查阅仓库内的完整变更记录 doc/en/changelog.rstpytest 3.7.3 小节位于第 7496 行起并对照 src/_pytest/capture.py 与 src/_pytest/python.py 的当前实现理解其设计意图。【免费下载链接】pytestThe pytest framework makes it easy to write small tests, yet scales to support complex functional testing项目地址: https://gitcode.com/GitHub_Trending/py/pytest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考