掌握了它,你就掌握了 Pytest 的核心!测试效率飙升!

部署运行你感兴趣的模型镜像

📝 面试求职: 「面试试题小程序」 ,内容涵盖 测试基础、Linux操作系统、MySQL数据库、Web功能测试、接口测试、APPium移动端测试、Python知识、Selenium自动化测试相关、性能测试、性能测试、计算机网络知识、Jmeter、HR面试,命中率杠杠的。(大家刷起来…)

📝 职场经验干货:

软件测试工程师简历上如何编写个人信息(一周8个面试)

软件测试工程师简历上如何编写专业技能(一周8个面试)

软件测试工程师简历上如何编写项目经验(一周8个面试)

软件测试工程师简历上如何编写个人荣誉(一周8个面试)

软件测试行情分享(这些都不了解就别贸然冲了.)

软件测试面试重点,搞清楚这些轻松拿到年薪30W+

软件测试面试刷题小程序免费使用(永久使用)


上篇文章为大家讲解了什么是测试用例发现、Pytest 的默认用例发现规则、Pytest 用例发现的内部流程。

今天,继续带大家深入聊聊我们日常工作中广泛使用的 Python 测试框架——Pytest的定制化测试发现规则、常见问题与排查技巧、总结与最佳实践。

文章导览

1. 什么是测试用例发现(Test Discovery)?

2. Pytest 的默认用例发现规则

3. Pytest 用例发现的内部流程:深入 Collection Phase(收集阶段)

4. 定制化你的测试发现规则

5. 常见问题与排查技巧(Troubleshooting)

6. 总结与最佳实践

7. 结语

定制化你的测试发现规则

虽然默认规则在大多数情况下够用,但有时我们需要根据项目特点调整发现行为。

Pytest 提供了多种方式进行定制:

1.  通过配置文件

这是最常用也推荐的方式。

在项目根目录下的 pytest.ini 文件

(或 pyproject.toml 中的 [tool.pytest.ini_options] 表,或 setup.cfg 中的 [tool:pytest] 段)中,你可以修改以下选项:

python_files

Glob 文件模式,用于匹配测试文件。可以设置多个模式,用空格分隔。

     [pytest]
     python_files = test_.py check_.py _spec.py

python_classes

Glob 类名模式,用于匹配测试类。可以设置多个模式。

注意,Test 前缀是默认包含的,除非你完全覆盖它。通常是添加模式,例如让 Check 开头的类也被识别。

     [pytest]
     python_classes = Test Check Suite

python_functions

 Glob 函数/方法名模式,用于匹配测试函数。可以设置多个模式。

     [pytest]
     python_functions = test_ check_ scenario_

norecursedirs

空格分隔的目录名模式列表,指定哪些目录在递归查找时应该被忽略。

     [pytest]
     norecursedirs = .git . venv dist build tmp docs

2.  通过命令行选项

--ignore=path

忽略指定的路径(文件或目录)。可以多次使用。

pytest --ignore=tests/legacy --ignore=tests/integration/test_slow.py

--ignore-glob=pattern

忽略匹配 glob 模式的路径。可以多次使用。

pytest --ignore-glob='_vendor/'

--collect-only 或 --co

只执行收集阶段,不执行测试。用于检查哪些测试会被发现,非常适合调试发现问题。配合 -q (quiet) 或 -v (verbose) 使用效果更佳。

     pytest --collect-only -q # 安静模式,只列出 Node ID
     pytest --collect-only -v # 详细模式,显示收集过程

3.  通过 conftest.py 文件

conftest.py 是 Pytest 的本地插件文件,它允许你在特定目录下定制 Pytest 行为,包括测试发现。

collect_ignore 列表

在 conftest.py 文件中定义一个名为 collect_ignore 的列表,包含相对于该 conftest.py 所在目录的子目录名或文件名字符串,这些路径将被忽略。

     # tests/conftest.py
     collect_ignore = ["helpers", "fixtures/data.py"] # 忽略 tests/helpers/ 目录和 tests/fixtures/data.py 文件

collect_ignore_glob 列表 (Pytest 6.0+)

类似于--ignore-glob,在 conftest.py 中定义 collect_ignore_glob 列表,包含 glob 模式。

   # tests/conftest.py
     collect_ignore_glob = ["_integration.py"] # 忽略所有以 _integration.py 结尾的文件

注意:

conftest.py 中的 collect_ignore 

和 collect_ignore_glob 只影响其所在目录及其子目录的收集行为。

实现 Collection Hooks

这是最高级的定制方式。你可以在 conftest.py 或安装的插件中实现 Pytest 的 Collection Hooks(收集钩子)来完全控制发现逻辑。

  • pytest_collect_file(path, parent): 

    决定是否要为一个给定的文件路径 path 创建一个 Module Collector。你可以返回一个自定义的 Collector 节点,或者返回 None 来阻止默认的收集行为。这对于收集非 Python 文件中的测试很有用。

  • pytest_pycollect_makemodule(path, parent): 

    定制 Module 节点的创建。

  • pytest_pycollect_makeitem(collector, name, obj): 

    当 Module 或 Class Collector 发现一个潜在的测试项(函数或方法 obj,名为 name)时调用。

    你可以返回一个自定义的测试项节点、多个节点(例如用于生成测试),或者返回 None 来阻止该项被收集。

  • pytest_collection_modifyitems(session, config, items): 

    如前所述,在收集完成后修改 items 列表。

使用 Collection Hooks 需要对 Pytest 的内部结构有较深的理解,通常用于插件开发或非常特殊的项目需求。

常见问题与排查技巧

 (Troubleshooting)

理解了原理,当遇到问题时就能更有条理地排查:

1.  测试用例没有被发现:

  • 检查命名: 

    是否符合 python_files, python_classes, python_functions 的模式?(最常见)

  • 检查 __init__: 

    测试类是否包含了 __init__ 方法?

  • 检查目录/文件是否被忽略: 

    是否在 norecursedirs 配置中?

    是否被 --ignore 或 conftest.py 中的

     collect_ignore / collect_ignore_glob 排除?

  • 检查语法错误: 

    文件是否能被 Python 正常导入?

    Pytest 在导入失败时会跳过该文件。

    运行 python -m py_compile path/to/your/test_file.py 检查。

  • 使用 pytest --collect-only -v:

    这是你的首选调试工具!它会显示 Pytest 尝试收集的每个文件和目录,以及为什么某些项被跳过或收集。仔细阅读其输出。

  • 检查 conftest.py: 

    是否有 conftest.py 中的钩子意外地阻止了收集?

2.  不希望执行的函数/类被当作测试执行了:

  • 检查命名: 

    是否意外地匹配了测试命名模式?(例如,一个辅助函数名为 test_helper())

  • 调整命名规则: 

    如果项目中有大量非测试代码遵循了默认模式,考虑在 pytest.ini 中使用更精确的模式,例如 python_functions = test_ test_scenario_,避免过于宽泛的模式。

  • 使用 _ 前缀: 

    Python 约定,以下划线 _ 开头的函数或类通常表示内部使用,Pytest 默认不会收集它们。可以将辅助函数命名为 _helper_function()。

  • 使用 pytest.mark.skip 

    或 pytest.mark.skipif: 

    如果只是临时不想执行某个测试,或者在特定条件下跳过,使用标记是更好的方式。

3.  __init__.py 文件在测试目录中的影响:

  • 在测试根目录或子目录中放置 __init__.py 文件会将其标记为 Python 包。这对于使用相对导入组织测试代码或 Fixture 是有用的。

  • 通常,它不会影响 Pytest 的文件和目录发现本身(Pytest 仍然会递归进入),但它会影响 Python 的模块导入行为。

  • 再次强调,测试类内部的 __init__ 方法会导致该类不被 Pytest 收集。

4.  收集阶段性能问题:

在非常大的项目中,如果收集阶段花费时间过长:

  • 确保 norecursedirs 配置包含了所有不需要检查的大型目录(如 node_modules, build 输出等)。

  • 检查是否有低效的 Collection Hooks。

  • 考虑拆分测试项目或更精细地指定要运行的测试子集。

  • 使用 pytest --collect-only --durations=0 查看收集各个文件的时间。

总结与最佳实践

Pytest 的用例发现机制是其易用性和强大功能的基石。通过理解其默认规则、内部收集流程以及各种定制化手段,我们可以:

  • 高效组织测试: 

    遵循约定,让 Pytest 自动完成繁琐的查找工作。

  • 灵活适应项目: 

    通过配置或钩子,让 Pytest 适应特殊的项目结构或测试类型。

  • 快速定位问题: 

    当发现行为不符合预期时,能有针对性地排查命名、配置或 conftest.py。

几点最佳实践建议:

1.  优先遵循默认约定: 

这是最简单、最通用、最易于团队协作的方式。

2.  保持清晰的目录结构: 

例如,将所有测试放在一个 tests/ 目录下,按功能或模块划分小子目录。

3.  谨慎使用 __init__: 

避免在测试类中使用 __init__ 方法,优先使用 Fixture 进行设置和拆卸。测试目录中的 __init__.py 按需使用。

4.  配置文件优于钩子: 

对于常见的定制需求(如修改命名模式、忽略路径),优先使用 pytest.ini 等配置文件,它们更直观易懂。仅在需要深度定制或实现插件时才使用 Collection Hooks。

5.  善用 --collect-only: 

它是你调试发现问题的得力助手。

结语

通过本文的学习,相信你已经掌握了 Pytest 的用例发现原理,并透析Pytest测试框架内部运作。

希望这本文能帮助你更熟练地驾驭 Pytest,编写出更健壮、更易于维护的自动化测试。

最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】

​​​

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值