ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

pytest 7.4.1 版本详解:三个关键缺陷修复与升级实践

pytest 7.4.1 版本详解:三个关键缺陷修复与升级实践 pytest 7.4.1 版本详解三个关键缺陷修复与升级实践【免费下载链接】pytestThe pytest framework makes it easy to write small tests, yet scales to support complex functional testing项目地址: https://gitcode.com/GitHub_Trending/py/pytest本篇文章基于 release-7.4.1.rst 发布公告并结合 doc/en/changelog.rst 中的完整变更日志与仓库源码系统梳理 pytest 7.4.1 的三个缺陷修复--import-modeimportlib的模块属性缺失、pytest.approx对字典中None值的比较异常、以及--import-modeimportlib与--doctest-modules组合时的重复导入问题。文章还涵盖从 7.4.0 升级到 7.4.1 的注意事项、相关源码佐证以及如何验证这些修复。pytest 7.4.1 是一个缺陷修复版本bug-fix release于 2023-09-02 发布定位为 7.4.0 的直接替代品drop-in replacement。它不引入新功能也不包含破坏性变更仅针对 7.4.0 中暴露的若干问题进行了针对性修复。升级命令与官方公告一致pip install --upgrade pytest升级完成后可执行pytest --version验证版本号是否为 7.4.1。目录一、版本定位bug-fix 版与 drop-in 升级二、修复详情三个缺陷逐一解析修复 1--import-modeimportlib下父模块丢失子模块属性修复 2pytest.approx在字典比较中错误处理None值修复 3--import-modeimportlib与--doctest-modules组合导致模块重复导入三、相关源码佐证四、升级与验证五、升级注意事项六、参考一、版本定位bug-fix 版与 drop-in 升级根据发布公告pytest 7.4.1 属于bug-fix 版本其核心特征是drop-in replacement可以直接替换 7.4.0无需修改测试代码或配置文件无新功能不增加任何 feature无破坏性变更不改变既有行为语义。这与 pytest 遵循的 Semantic Versioning语义化版本 策略一致major.minor.patch中的 patch 版本只包含向后兼容的缺陷修复。版本号规范在 doc/en/changelog.rst 中有明确说明。二、修复详情三个缺陷逐一解析根据 doc/en/changelog.rst 中 7.4.1 章节本次修复包含三个缺陷修复 1--import-modeimportlib下父模块丢失子模块属性问题编号pytest-dev/pytest#10337影响范围使用--import-modeimportlib的项目问题描述当使用--import-modeimportlib时pytest 会生成一些伪造的中间模块fake intermediate modules来模拟包结构。在 7.4.0 及更早版本中这些中间模块不会将子模块作为属性挂载到父模块上。这会导致类似import pkg.subpkg.module的导入链在子模块访问父模块属性时出现问题。从源码理解 import-mode在 src/_pytest/config/init.py 中可以看到pytest 的配置系统维护importmode参数并针对不同 import 模式执行相应的导入路径处理。importlib模式使用 Python 标准库的importlib机制按 spec 加载模块与默认的prepend模式将测试目录插入sys.path最前端在模块解析方式上有本质区别。--import-modeimportlib的价值在于避免sys.path污染、支持同名模块的隔离加载在大型测试仓库中尤为有用。修复效果7.4.1 确保伪造中间模块正确地将子模块注册为父模块的属性使importlib模式下的模块层级行为与正常 Python 导入语义一致。修复 2pytest.approx在字典比较中错误处理None值问题编号pytest-dev/pytest#10702影响范围使用pytest.approx()比较包含None值的字典dict时问题描述当使用pytest.approx比较两个字典且期望值或实际值中包含None时7.4.0 会触发错误的断言处理error assertion handling导致比较失败或产生误导性的错误信息。例如import pytest # 期望字典中的某个键对应 None expected {a: 1.0, b: None} actual {a: 1.0, b: None} # 7.4.0 中可能错误地抛出异常或给出误导性报错 assert expected pytest.approx(actual)从源码理解pytest.approx对字典的比较由 src/_pytest/approx.py 中的ApproxMapping类实现。其比较逻辑为先检查两个映射的长度是否一致再检查键集合是否一致最后逐键比较值通过_approx_scalar构造近似对象进行容差比较。关键修复点在 src/_pytest/approx.pyif approx_value.expected is not None and other_value is not None:这一行显式排除None值参与数值容差计算。在 7.4.1 修复之前当approx_value.expected或other_value为None时代码会尝试对None执行算术运算如abs(expected - other)或除法从而触发类型错误或ZeroDivisionError等异常。修复后None值被正确地视为非数值不再进入容差运算路径。此外src/_pytest/approx.py 中还包含对嵌套字典的明确限制pytest.approx不支持嵌套字典遇到时会抛出带详细上下文的异常信息这也是ApproxMapping设计的一部分。修复效果7.4.1 中当比较的字典值包含None时pytest.approx能够正确判定相等性None None而不会抛出异常或误报失败。若一侧为None而另一侧为数值则正常判定为不相等并给出差异说明。修复 3--import-modeimportlib与--doctest-modules组合导致模块重复导入问题编号pytest-dev/pytest#10811影响范围同时使用--import-modeimportlib与--doctest-modules的项目问题描述当两个选项组合使用时pytest 会将同一模块导入多次。对于具有导入副作用import side effects的模块——例如模块级代码会写文件、启动连接、注册全局状态等——重复导入会导致副作用被重复执行全局状态被意外重置或污染测试结果不可预测。从源码理解--doctest-modules让 pytest 收集所有 Python 模块中的 doctest 作为测试项。在importlib模式下模块通过 src/_pytest/assertion/rewrite.py 中的AssertionRewritingHook一个MetaPathFinder与Loader的组合进行加载。该 Hook 调用importlib.util.spec_from_file_location为模块创建 spec并参与 Python 的元路径查找机制。若模块在 doctest 收集路径与常规收集路径下被重复触发加载就可能出现多次导入。修复效果7.4.1 确保在importlibdoctest-modules组合下模块只被导入一次消除了重复导入带来的副作用问题。三、相关源码佐证pytest 7.4.1 的三个修复均可在当前仓库源码中找到对应的实现基础修复项源码位置关键实现importlib 中间模块属性src/_pytest/config/init.pyimportmode参数处理与导入路径管理approx 对 None 的处理src/_pytest/approx.pyif approx_value.expected is not None and other_value is not None:条件保护模块重复导入src/_pytest/assertion/rewrite.pyAssertionRewritingHook的 spec 创建逻辑在测试侧pytest.approx的行为覆盖在 testing/python/approx.py 中其中包含针对错误消息和容差计算的多种断言测试。--import-modeimportlib与 doctest 相关的回归测试则位于 testing/ 目录的对应测试模块中。四、升级与验证升级到 pytest 7.4.1 的完整流程# 1. 升级 pytest pip install --upgrade pytest # 2. 验证版本 pytest --version # 期望输出包含 pytest 7.4.1 # 3. 验证修复 1 与修复 3importlib 模式 pytest --import-modeimportlib --doctest-modules tests/ # 模块只导入一次无重复导入副作用 # 4. 验证修复 2approx 与 None python -c import pytest expected {a: 1.0, b: None} actual {a: 1.0, b: None} assert expected pytest.approx(actual) print(approx None comparison OK) 对于受影响的场景建议在升级后重点回归以下测试使用--import-modeimportlib的项目检查涉及包内相对导入、父模块属性访问的测试使用pytest.approx比较含None值字典的测试同时开启--import-modeimportlib --doctest-modules的项目检查模块级副作用是否正常。五、升级注意事项虽然 7.4.1 是 drop-in 版本但结合 7.4.0 引入的改进仍有几点值得留意来自 doc/en/changelog.rst 中 7.4.0 章节testpaths警告#11013当testpaths配置的路径通过 glob 匹配不到任何文件时pytest 会发出警告并回退到从当前目录搜索。升级后若出现此警告请检查testpaths配置是否正确。--confcutdir行为变化#11043未指定--confcutdir且无配置文件时conftest 截止目录现在默认设置为 rootdir而不是一直探测到文件系统根目录。若依赖旧的探测行为建议显式设置--confcutdir或添加空配置文件。norecursedirs检查迁移#11081norecursedirs检查现在在pytest_ignore_collecthook 实现中执行。若升级后发现norecursedirs未被遵守通常是某个 conftest 或插件的pytest_ignore_collect实现返回了False而非None导致提前终止处理修复方式是改为返回None。六、参考发布公告doc/en/announce/release-7.4.1.rst完整变更日志doc/en/changelog.rst 中 pytest 7.4.1 章节上一版本公告doc/en/announce/release-7.4.0.rst版本规范doc/en/changelog.rst 中的语义化版本说明【免费下载链接】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),仅供参考
返回列表