首页 > 其他分享 >关键字 开发-01 pytest收集yaml用例

关键字 开发-01 pytest收集yaml用例

时间:2023-11-23 10:22:53浏览次数:37  
标签:01 Module yaml pytest file test path

1.pytest收集测试用例规则

pytest框架在收集用例的时候,默认会查找test_开头的.py 模块,并且在模块中找到test_ 开头的函数或Test开头的类。
根据这个规则,如果我们想收集yaml格式的文件当用例执行,需解决2个问题:

1.修改用例收集规则,改成收集yaml格式文件作为收集的目标
2.将yaml文件生成pytest的测试用例

pytest 在运行的时候,以你运行的目录,往上查找 conftest.py 文件,以 pytest.ini 所在的目
录为根路径。

test_a.py

def test_1():
    print('hello')

def test_2():
    print('world')

打断点运行查看:

从图中我们可以清楚的知道:

1.每个用例最终会转成 一个 Function 对象:
2.Function 对象的上一层(parent ) 是 Module 模块对象:Module test_a.py
3.Module 模块的上一层是 Package 包,Package 包的上一层是 session 对象

于是我们知道pytest 收集用例的基本思路:

2. 如何构造pytest的item用例

从上面可以知道,构造pytest的item,需要:1.构造Package,2.构造Module, 3.构造Function
查看Function的源码:> from pytest import Function, Module

于是可以知道,基本思想是利用 Module 构建 Function!其调用伪代码如下: > Function.from_parent(Module)
既然可以利用 Module 构建 Function, 那如何构建 Module ? 当然是利用 Package 构建
Module!> Module.from_parent(Package)
既然可以利用 Package 构建 Module 那如何构建 Package ? 请看下图调用关系:

pytest 从 Config 开始,层层构建,直到 Function !Function 是 pytest 的最小执行单元。 手动
构建 item 就是模拟 pytest 构建 Function 的过程。也就是说,需要创建 Config ,然后利用
Config 创建 Session ,然后利用 Session 创建 Package ,…,最后创建 Function。
pytest 会自动创建好 Config, Session 和 Package ,这三者不用手动创建。

2. yaml文件构建成Module模块喝用例

先通过 pytest_collect_file 钩子收集到指定yaml文件用例。

# conftest.py
from pytest import Module
import types
def pytest_collect_file(file_path, parent):
  # 查找test 开头的yaml 文件
  if file_path.suffix in [".yml", ".yaml"] and (file_path.name.startswith("test") or file_path.name.endswith("test")):
    print(f"yaml 文件的路径:{file_path}")
    print(f"yaml 文件的名称:{file_path.stem}")
    # 构造 pytest 框架的 Module
    py_module = Module.from_parent(parent, path=file_path)
    # 动态创建
    MyModule = types.ModuleType(file_path.stem)
    # 重写_getobj
    py_module._getobj = lambda: MyModule
    return py_module

步骤1:先通过Module 类构造pytest 框架的 Module 用例模块

构造 pytest 框架的 Module
py_module = Module.from_parent(parent, path=file_path)

由于是一个yaml 文件,它不是一个真正的py模块,Module 类里面有个 _getobj 方法是 import
python的模块,yaml 文件是不能import 的,所以我们需要重新 _getobj 方法
以下是Module 类相关源码

class Module(nodes.File, PyCollector):
  """Collector for test classes and functions."""
  def _getobj(self):
    return self._importtestmodule()

步骤2:yaml 文件如何变成 py模块?这是解决问题的关键点,其实很简单,我们自己动态构造一个模块
就行了,一句代码就能解决.

动态创建模块
MyModule = types.ModuleType('test_x')

步骤3:到这里问题解决了一半,yaml 文件已经被我们动态构造成了 pytest 框架的 Module。
接下来我们需要解决另外一个问题,通过 Module 构造生成 Function 用例。Function 用例不需要再用类似于 Function.from_parent(parent) 这种方式构建了,我们只需要
给 Module 模块对象添加test开头的函数,它就会自动变成用例。

def run_function(*args, **kwargs):
  print("执行测试用例-----")
  # 向 module 中加入test 函数
  setattr(MyModule, "test_run", run_function)

完整的 conftest.py 中代码如下:

from pytest import Function, Module
import types
 def pytest_collect_file(file_path, parent):
  # 查找test 开头的yaml 文件
  if file_path.suffix in [".yml", ".yaml"] and (file_path.name.startswith("test") or file_path.name
    print(f"yaml 文件的路径:{file_path}")
    print(f"yaml 文件的名称:{file_path.stem}")
    # 构造 pytest 框架的 Module
    py_module = Module.from_parent(parent, path=file_path)
    # 动态创建
    MyModule = types.ModuleType(file_path.stem)
    def run_function(*args, **kwargs):
    print("测试用例-----")
    # 向 module 中加入test 函数
    setattr(MyModule, "test_run", run_function)
    # 重写_getobj
    py_module._getobj = lambda: MyModule
    return py_module

然后我们随便写一个空的 test_x.yaml 文件,它都能执行了

到这里我们所做的事情就非常清晰了,把yaml 文件动态生成 python 的模块。并通过钩子函数方法构造成pytest 框架的 Module 对象。
yaml文件的内容暂时是写死的一个固定函数执行,下一篇讲读取yaml文件内容按关键字执行。

标签:01,Module,yaml,pytest,file,test,path
From: https://www.cnblogs.com/dack-zt-deng/p/17849937.html

相关文章

  • P4180 [BJWC2010] 严格次小生成树
    如果有两条在最小生成树上的边被换掉了,那么原树会被分成三个连通块。考虑新加的两条边,保留权值较小的那一条,这样还剩两个连通块。而删除的两条边至少有一条能连通这两个连通块,所以可以保留那条边。并且新加的两条边中权值较大的那一条肯定大于等于我们保留的边,否则与最小生成树......
  • (字符串)01-字符串变形
    1importjava.util.*;23publicclassSolution{4/**5*@paramsstring字符串6*@paramnint整型7*@returnstring字符串8*/9publicStringtrans(Strings,intn){10//校验字符串长度11if......
  • 001swagger2--接口文档生成利器
    1.配置在springboot整合swagger21.1引入jar包<dependency><groupId>com.allen.pan</groupId><artifactId>allen-pan-core</artifactId><version>1.0</version></dependency&g......
  • DOJ-team-match 9-2017篮球队
    题面一道动态规划题\(f_{i, j, k}\)表示前i个人里取j个,身高大于等于k的方法数得到状态转移方程为\(f_{i, j, k} = f_{i − 1, j − 1, k − a_i}\)由于这样空间不够,我们需要降维代码:#include<bits/stdc++.h>usingnamespacestd;constintMAXN=2e5+5;int......
  • day01
    【一】下载Typora软件【1】下载官网Typora官方中文站(typoraio.cn)【2】破解(1)自己搜(2)直接用1.方法一下载资源到本地D:\Typora\resources文件夹下替换破解成功2.方法二下载资源到本地解压将文件复制到.\Typora(软件文件夹)里【二】markdo......
  • 【题解】HD2016.X1,HD2016.X3,HD2016.X4,HD2016.X5
    [HD2016.X1]价钱统计题目描述夏天到了,超市里摆满了各种各样的应季水果。现在知道:西瓜的价钱是每斤1.2元;桃子的价钱是每斤3.5元;葡萄的价钱是每斤4.5元;苹果的价钱是每斤5元。现在分别给出上述四种所购买的斤数(均不超过20),请你编写程序帮助售货员阿姨计算并依次输出顾客......
  • CSC1001 编程方法描述
    您应该在.py文件中为每个问题编写代码(请使用问题名称,例如,对于问题1,将其命名为q1.py)。请将所有.py文件打包到一个.zip文件,使用您的学生ID命名(例如,如果您的学生标识是123456,则文件应命名为123456.zip),然后通过Blackboard提交.zip文件。还请编写一个文本文件,其中提供了如何为每个代......
  • EEEN30141 Concurrent Systems
    该课程分为三个部分,将四个部分合在一起进行模拟百米短跑接力赛。比赛由NO_TEAMS参赛队和每个团队都有NO_MEMBERS成员。NO_TEAMS和NO_MEMBERS都是四个。课程的三个部分如下:•第1部分:这涉及创建和启动一个二维数组线程,每个线程代表一个runner,询问线程属性,以及使用随机数和时间......
  • 面向对象01:什么是面向对象
    属性+方法=类  ......
  • [IOI2015] Teams 题解
    妙妙题。不难发现,我们对于每个\(k\)取出的人都是满足\(a_i\leqk\leqb_i\)的。经典的,我们直接将\((a_i,b_i)\)转化到二维平面上,将它转化成一个二维数点问题。我们对于每一个询问,都使\(k\)有序,从小到大贪心的选择,也就相当于\(x\)轴限制不断向右,\(y\)轴限制不断......