背景:

  根据以下简单的代码示例,我们将从源码的角度分析其中的关键加载执行步骤,对pytest整体流程架构有个初步学习。

代码示例:

import pytest

def test_add():

assert 1 + 1 == 2

def test_sub():

assert 2 - 1 == 1

  通过 pytest test_example.py 运行此代码示例后,会触发pytest的入口函数main(),这个函数定义在src/pytest/__main__.py中,它的作用是创建一个PytestConfig对象,并调用其

do_configure()和do_main()方法。PytestConfig对象是pytest的核心配置类,它负责解析命令行参数、读取配置文件、注册插件、创建Session对象等。PytestConfig对象定义在

src/_pytest/config/__init__.py中,它继承了pluggy.HookimplMarker类,也就是说它可以作为一个插件管理器,调用各种hook函数。

```python
# src/pytest/__main__.py def main():
# 创建PytestConfig对象
config = PytestConfig()
# 调用config.do_configure()方法
config.do_configure()
# 调用config.do_main()方法
config.do_main()
``` ```python
# src/_pytest/config/__init__.py class PytestConfig(pluggy.HookimplMarker):
def __init__(self):
# 解析命令行参数
self.parse_args()
# 读取配置文件
self.read_config_files()
# 注册插件
self.register_plugins()
# 创建Session对象
self.session = Session(self) def do_configure(self):
# 调用hook函数pytest_configure
self.hook.pytest_configure(config=self) def do_main(self):
# 调用hook函数pytest_sessionstart
self.hook.pytest_sessionstart(session=self.session)
# 调用Session对象的main()方法
self.session.main()
```
 

  Session对象是pytest的核心上下文类,它负责管理整个测试过程的信息,包括收集测试用例、执行测试用例、生成测试报告等。Session对象定义在src/_pytest/main.py中,它继承了

Collector类,也就是说它可以作为一个测试用例收集器。Session对象的main()方法是执行测试用例的主要入口,它会调用perform_collect()方法来收集测试用例,并返回一个列表items;然后

调用runtestloop()方法来循环执行items中的每个Item对象;最后调用hook函数pytest_sessionfinish来结束测试会话,并返回一个退出码exitstatus。

```python
# src/_pytest/main.py class Session(Collector):
def __init__(self, config):
# 初始化一些属性和状态信息 def main(self):
# 调用perform_collect()方法收集测试用例,并返回items列表
items = self.perform_collect()
# 调用runtestloop()方法循环执行items中的每个Item对象,并返回退出码exitstatus
exitstatus = self.runtestloop(items)
# 调用hook函数pytest_sessionfinish来结束测试会话,并返回退出码exitstatus
self.hook.pytest_sessionfinish(session=self, exitstatus=exitstatus)
return exitstatus def perform_collect(self):
# 调用hook函数pytest_collectstart表示开始收集测试用例
self.hook.pytest_collectstart(collector=self)
# 调用自身的collect()方法来递归遍历指定的测试文件或目录,并返回一个列表items
items = self.collect()
# 调用hook函数pytest_collectreport表示收集测试用例结束,并生成收集报告
self.hook.pytest_collectreport(report=CollectReport(self, "passed", items))
# 调用hook函数pytest_collection_modifyitems允许对收集到的Item对象进行修改
self.hook.pytest_collection_modifyitems(session=self, config=self.config, items=items)
# 调用hook函数pytest_deselected表示从收集到的Item对象中筛选出需要执行的Item对象
self.hook.pytest_deselected(items=self.deselected)
# 调用hook函数pytest_collection_finish表示收集和筛选测试用例完成,并返回最终要执行的Item对象列表
self.hook.pytest_collection_finish(session=self)
return items def runtestloop(self, items):
# 调用hook函数pytest_runtestloop表示开始循环执行测试用例
self.hook.pytest_runtestloop(session=self)
# 遍历items列表,依次取出每个Item对象
for item in items:
# 调用Item对象的runtestprotocol()方法来执行单个测试用例的协议
item.runtestprotocol()
# 返回退出码0表示成功
return 0
```

  

  Item对象是pytest的核心测试类,它负责封装和执行单个测试用例的信息,包括名称、位置、参数化信息、标记信息等。Item对象定义在src/_pytest/python.py中,它继承了Node类,也

就是说它可以作为一个测试节点。Item对象的runtestprotocol()方法是执行单个测试用例的主要入口,它会调用hook函数pytest_runtest_logstart来开始记录日志信息;然后调用runtest()方法

来执行测试用例的前置、主体和后置部分;最后调用hook函数pytest_runtest_logfinish来结束记录日志信息,并生成日志报告。

```python
# src/_pytest/python.py class Item(Node):
def __init__(self, name, parent, config, session):
# 初始化一些属性和状态信息 def runtestprotocol(self):
# 调用hook函数pytest_runtest_logstart表示开始记录日志信息
self.ihook.pytest_runtest_logstart(nodeid=self.nodeid, location=self.location)
# 调用runtest()方法来执行测试用例的前置、主体和后置部分,并返回一个列表reports
reports = self.runtest()
# 调用hook函数pytest_runtest_logfinish表示结束记录日志信息,并生成日志报告
self.ihook.pytest_runtest_logfinish(nodeid=self.nodeid, location=self.location)
return reports def runtest(self):
# 创建一个空列表reports
reports = []
# 调用_setup()方法来执行测试用例的前置操作,并将返回的报告添加到reports列表中
reports.append(self._setup())
# 如果前置操作没有失败或跳过,则调用_call()方法来执行测试用例的主体部分,并将返回的报告添加到reports列表中
if reports[-1].passed:
reports.append(self._call())
# 调用_teardown()方法来执行测试用例的后置操作,并将返回的报告添加到reports列表中
reports.append(self._teardown())
# 返回reports列表
return reports def _setup(self):
# 调用hook函数pytest_runtest_setup表示开始执行前置操作,并返回一个报告setup_report
setup_report = self.ihook.pytest_runtest_setup(item=self)
return setup_report def _call(self):
# 调用hook函数pytest_runtest_call表示开始执行主体部分,并返回一个报告call_report
call_report = self.ihook.pytest_runtest_call(item=self)
return call_report def _teardown(self):
# 调用hook函数pytest_runtest_teardown表示开始执行后置操作,并返回一个报告teardown_report
teardown_report = self.ihook.pytest_runtest_teardown(item=self)
return teardown_report
```

总结:

Pytest的加载流程大致如下:

- Pytest首先会解析命令行参数,确定要执行的测试文件、测试目录、测试类、测试函数等,以及一些配置选项。
- Pytest会根据配置文件(pytest.ini、setup.cfg、tox.ini等)和命令行参数,创建一个Config对象,用于存储配置信息。
- Pytest会创建一个Session对象,用于管理整个测试过程的上下文信息,包括收集测试用例、执行测试用例、生成测试报告等。
- Pytest会调用hook函数pytest_sessionstart,表示测试会话开始。
- Pytest会调用hook函数pytest_collectstart,表示开始收集测试用例。
- Pytest会根据Config对象中的信息,递归遍历指定的测试文件或目录,寻找符合pytest约定的测试用例(以test_开头的函数或方法,以Test开头的类等)。
- Pytest会将找到的测试用例封装成Item对象,并添加到Session对象的items列表中。Item对象包含了测试用例的名称、位置、参数化信息、标记信息等。
- Pytest会调用hook函数pytest_collectreport,表示收集测试用例结束,并生成收集报告。
- Pytest会调用hook函数pytest_collection_modifyitems,允许对收集到的Item对象进行修改,例如重新排序、添加或删除标记等。
- Pytest会调用hook函数pytest_deselected,表示从收集到的Item对象中筛选出需要执行的Item对象,并将不需要执行的Item对象放入Session对象的deselected列表中。
- Pytest会调用hook函数pytest_collection_finish,表示收集和筛选测试用例完成,并返回最终要执行的Item对象列表。
- Pytest会根据是否使用多进程或多线程模式,创建相应的WorkerController对象,用于管理多个Worker对象。Worker对象负责执行具体的测试用例,并将结果返回给WorkerController对象。
- Pytest会调用hook函数pytest_runtestloop,表示开始循环执行测试用例。
- Pytest会遍历Session对象中的items列表,依次取出每个Item对象,并调用hook函数pytest_runtest_protocol,表示开始执行单个测试用例的协议。
- Pytest会调用hook函数pytest_runtest_logstart,表示开始记录单个测试用例的日志信息。
- Pytest会调用hook函数pytest_runtest_setup,表示开始执行单个测试用例的前置操作(例如setup函数或方法)。
- Pytest会调用hook函数pytest_runtest_call,表示开始执行单个测试用例的主体部分(例如测试函数或方法)。
- Pytest会调用hook函数pytest_runtest_teardown,表示开始执行单个测试用例的后置操作(例如teardown函数或方法)。
- Pytest会调用hook函数pytest_runtest_logfinish,表示结束记录单个测试用例的日志信息,并生成日志报告。
- Pytest会调用hook函数pytest_runtest_makereport,表示根据单个测试用例的执行结果,生成测试报告(包括setup、call和teardown三个阶段的报告)。
- Pytest会重复上述步骤,直到所有的Item对象都被执行完毕。
- Pytest会调用hook函数pytest_sessionfinish,表示测试会话结束,并生成最终的测试报告(包括所有Item对象的报告)。
- Pytest会调用hook函数pytest_terminal_summary,表示在终端输出最终的测试结果和统计信息。

Pytest 框架执行用例流程浅谈的更多相关文章

  1. pytest框架执行自动化测试时使用pycharm正常运行,使用cmd或Terminal报错:Hint: make sure your test modules/packages have valid Python names.

    问题描述: 使用pytest框架做接口自动化测试时,在测试用例所在的.py文件下使用pycharm的run功能可以正常跑用例,使用cmd运行窗口或Terminal则报下图中的错误: Hint: mak ...

  2. 【Pytest05】全网最全最新的Pytest框架之用例分组执行

    一.Fixture用例分组运行常用于冒烟测试,分模块运行等 pytest.ini配置文件中增加分组参数markers来实现用例分组,如: markers = g1:组一 smoke:冒烟测试 pyte ...

  3. Pytest(15)pytest分布式执行用例

    前言 平常我们功能测试用例非常多时,比如有1千条用例,假设每个用例执行需要1分钟,如果单个测试人员执行需要1000分钟才能跑完 当项目非常紧急时,会需要协调多个测试资源来把任务分成两部分,于是执行时间 ...

  4. 『德不孤』Pytest框架 — 3、Pytest的基础说明

    目录 1.Pytest参数介绍 2.Pytest框架用例命名规则 3.Pytest Exit Code说明 4.pytest.ini全局配置文件 5.Pytest执行测试用例的顺序 1.Pytest参 ...

  5. requests接口自动化-pytest框架

    pytest框架规则 测试文件以test_开头或者以_test结尾 测试类以Test开头,并且不能带有init方法 测试函数以test_开头 断言使用assert pytest框架运行用例 运行单个文 ...

  6. SDUT OJ 数据结构实验之串一:KMP简单应用 && 浅谈对看毛片算法的理解

    数据结构实验之串一:KMP简单应用 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descr ...

  7. Pytest测试框架(一):pytest安装及用例执行

    PyTest是基于Python的开源测试框架,语法简单易用,有大量的插件,功能非常多.自动检测测试用例,支持参数化,跳过特定用例,失败重试等功能. 安装 pip install -U pytest  ...

  8. 浅谈Java的集合框架

    浅谈Java的集合框架 一.    初识集合 重所周知,Java有四大集合框架群,Set.List.Queue和Map.四种集合的关注点不同,Set 关注事物的唯一性,List 关注事物的索引列表,Q ...

  9. 浅谈java类集框架和数据结构(2)

    继续上一篇浅谈java类集框架和数据结构(1)的内容 上一篇博文简介了java类集框架几大常见集合框架,这一篇博文主要分析一些接口特性以及性能优化. 一:List接口 List是最常见的数据结构了,主 ...

  10. 浅谈 iOS 与 H5 的交互- JavaScriptCore 框架

    前言 小的作为一个iOS程序猿,可能研究JavaScript以及H5相关的知识并不是为了真正的要去转行做这一方面,其实更多的为了要研究OC中的JavaScriptCore框架,JavaScriptCo ...

随机推荐

  1. ICANN 2001-Learning to Learn Using Gradient Descent

    Key Gradient Descent+LSTM元学习器 解决的主要问题 在之前的机器学习的学习方法中,不会利用到之前的经验,利用到之前经验的"knowledge transfer&quo ...

  2. ODOO13之12:Odoo 13开发之报表和服务端 QWeb

    报表是业务应用非常有价值的功能,内置的 QWeb 引擎是报表的默认引擎.使用 QWeb 模板设计的报表可生成 HTML 文件并被转化成 PDF.也就是说我们可以很便捷地利用已学习的 QWeb 知识,应 ...

  3. Java方法的调用以及方法参数传递、方法的递归调用

    一.方法的调用以及方法参数传递 1.方法的定义: ​ 访问修饰符 返回值类型 方法名 ([参数列表]){ ​ 方法体 } 如果方法体中需要一些未知的数据作为执行条件,那么这些数据可以作为参数. 如果方 ...

  4. 精彩回顾 | 金蝶云苍穹技术开放日xUser Club广州站

    6月14日,以"项目实践案例:性能优化与实践"为主题的金蝶云·苍穹技术开放日广州站圆满落幕.此次活动吸引了50多位开发者到场,大家不仅聆听了开发者关于"代码检查.性能优化 ...

  5. 使用 Easysearch 还原 Elasticsearch 快照数据

    本文主要验证 Elasticsearch 快照在 Easysearch 中进行数据恢复. 准备测试数据 索引 别名 模版 生命周期策略 创建快照 PUT /_snapshot/my_backup { ...

  6. [ARM 汇编]进阶篇—异常处理与中断—2.4.2 ARM处理器的异常向量表

    异常向量表简介 在ARM架构中,异常向量表是一组固定位置的内存地址,它们包含了处理器在遇到异常时需要跳转到的处理程序的入口地址.每个异常类型都有一个对应的向量地址.当异常发生时,处理器会自动跳转到对应 ...

  7. FPGA加速技术详解:从原理到应用

    目录 FPGA加速技术详解:从原理到应用 背景介绍: 随着计算机性能的不断提高和运算能力的增强,GPU.CPU等高性能计算硬件已经可以满足大部分计算任务的需求.然而,对于大规模.复杂的实时数据处理和高 ...

  8. asp.net程序通过Microsoft Azure令牌授予流获取UserInfo终结点实现单点登录--隐式授予流(OIDC协议)

    1. Microsoft Azure令牌授予流 令牌授予流种类如下: 本章节采用: 隐式授予流: 2. 隐式授予流的实现 流程:重定向到authorize--->拿到access_token-- ...

  9. iis7以上 ssl 证书导入

    证书导入 开始 -〉运行 -〉MMC: 启动控制台程序,选择菜单"文件"中的"添加/删除管理单元"-> "添加",从"可用的 ...

  10. HCL实验6:静态路由

    拓扑图 步骤: 连线,路由器与路由器通过S端口连接 配置好PC 配置路由器端口IP 配置路由器的下一跳地址(静态路由) 详细步骤 连线情况可见拓扑图 配置好PC 端口IP R1 [R1]int g0/ ...