元类在测试框架中的运用
元类在测试框架中的运用
书接上回
我们知道了元类的基本用法,也写了一个小demo,接下来我们就尝试运用进我们测试框架。
#一款无需编码且易用于二次开发的接口测试框架。
#我写的我写的我写的我写的
pip install mwj-apitest
#这里面就用到了元类,教程还在写,有兴趣的可以玩一玩,还有一些bug,还有很多地方没完善,前几天让一位大佬帮忙测试了,windows和mac都可以运行哦。
#目前最新版本是1.2.3
知识回顾
type(name, bases, dcit)
- name : 表示要创建的类的名称。(字符串类型)
- bases : 继承类的基类元组(或包含基类的元类)。(元组类型)
- dict : 类属性和方法。(字典类型)
动态创建用例
# 使用type去创建用例类
from unittest import TestCase# 通过type动态去生成测试类
MyTest = type('MyTest', (TestCase,), {"cases": [11, 22, 33, 44], 'test_1': lambda x: x, 'test_2': lambda x: x})if __name__ == '__main__':import unittestimport unittestreportsuite = unittest.defaultTestLoader.loadTestsFromTestCase(MyTest)unittestreport.TestRunner(suite).run()
运行结果:
test_1 (__main__.MyTest)执行——>【通过】
test_2 (__main__.MyTest)执行——>【通过】
所有用例执行完毕,正在生成测试报告中......
测试报告已经生成,报告路径为:./reports\report.html
上面通过元类动态创建测试类及测试方法部分的代码等同于如下代码:
from unittest import TestCase
class MyTest(TestCase):cases = [11, 22, 33, 44]test_1 = lambda x: xtest_2 = lambda x: x
等价于:
from unittest import TestCaseclass MyTest(TestCase):cases = [11, 22, 33, 44]@classmethoddef test_1(cls, x):return x@classmethoddef test_2(cls, x):return x
自定义解析测试用例的元类
准备一手测试数据,在同级目录下创建test_data.json文件
[{"title": "测试用例1","data": "参数1"},{"title": "测试用例2","data": "参数2"},{"title": "测试用例3","data": "参数3"}
]
from functools import wraps
import unittestdef update_test_func(func, value):@wraps(func)def wrapper(self, **kwargs):return func(self, value)return wrapperclass MyMateClass(type):def __new__(cls, name, bases, attrs, *args, **kwargs):# 通过元类创建一个类test_cls = super().__new__(cls, name, bases, attrs)# 遍历属性Casesfor index, value in enumerate(attrs['Cases']):# func =test_cls.test_performfunc = getattr(test_cls, 'perform')test_func = update_test_func(func, value)# 动态给test_cls这个类 添加方法setattr(test_cls, 'test_{}'.format(index), test_func)return test_clsclass BaseApiCase:"""用例执行的基本类"""def perform(self, case):"""用例执行的方法"""print("测试数据:", case)# 1、用例数据的处理# 2、接口请求# 3、响应数据提取# 4、断言if __name__ == '__main__':import unittestreportimport json# 通过自定义的元类创建类with open('test_data.json', 'r', encoding='utf-8') as f:cases = {'Cases': json.load(f)}Xiaozai = MyMateClass('Xiaozai', (unittest.TestCase, BaseApiCase), cases)# # 加载测试类的用例到测试套件suite = unittest.defaultTestLoader.loadTestsFromTestCase(Xiaozai)# 运行用例unittestreport.TestRunner(suite, templates=2).run()
执行结果如下:
测试数据: {'title': '测试用例1', 'data': '参数1'}
test_0 (__main__.Xiaozai)执行——>【通过】
测试数据: {'title': '测试用例2', 'data': '参数2'}
test_1 (__main__.Xiaozai)执行——>【通过】
测试数据: {'title': '测试用例3', 'data': '参数3'}
test_2 (__main__.Xiaozai)执行——>【通过】
所有用例执行完毕,正在生成测试报告中......
测试报告已经生成,报告路径为:./reports\report.html
代码解析
这段代码实现了一个自定义元类MyMateClass,通过该元类动态创建测试用例类Xiaozai。
- 导入需要的模块:
wraps函数:用于保留被装饰函数的元信息。unittest模块:包含了用于编写和运行单元测试的功能。unittestreport模块:一个第三方模块,用于生成测试报告。- 可以通过
pip install unittestreport进行下载。
- 可以通过
json模块:用于处理和解析JSON数据。
- 定义修饰器函数
update_test_func:- 该函数接受一个测试方法和参数值作为输入。
- 在内部定义一个装饰器函数
wrapper,用于修改测试方法的调用方式。 wrapper函数将调用被装饰的测试方法,传递参数值作为参数,并返回结果。- 最后,将装饰器函数
wrapper返回。
- 定义元类
MyMateClass:- 重写
__new__方法,在创建新类时动态添加测试方法。 - 遍历
attrs['Cases']中的测试用例数据。 - 通过调用
getattr函数获取基类BaseApiCase中的测试方法perform。 - 使用修饰器函数
update_test_func对测试方法进行修饰,并设置修饰后的方法名为'test_{}'.format(index)。test_0,test_1,test_2。 - 使用
setattr函数将修饰后的测试方法添加到新创建的类test_cls中。
- 重写
- 定义基类
BaseApiCase:BaseApiCase类定义了一个名为perform的测试方法,该方法接受一个参数case。- 在该方法中,打印了测试用例数据,并且可以进行数据处理、接口请求、响应数据提取和断言等操作。
- 在
__main__中运行测试用例:- 通过
open函数打开测试用例数据文件,并加载JSON数据。 - 创建包含测试用例数据的字典
cases。 - 使用自定义的元类
MyMateClass创建测试用例类Xiaozai,该类继承自unittest.TestCase和BaseApiCase。 - 使用
unittest.defaultTestLoader.loadTestsFromTestCase函数,将测试用例类中的用例加载到测试套件中。 - 创建
unittestreport.TestRunner对象,并使用run方法运行测试套件,生成测试报告。
- 通过
知识点扩展setter()
源码展示:
def setattr(x, y, v): # real signature unknown; restored from __doc__"""Sets the named attribute on the given object to the specified value.setattr(x, 'y', v) is equivalent to ``x.y = v''"""pass
setattr(x, y, v)函数是Python内置函数之一,用于设置对象x的属性y的值为v。具体解析如下:
x:表示需要设置属性的对象。y:表示需要设置的属性名。v:表示需要设定的属性值。
setattr(x, y, v)函数的作用是将对象x的属性y设置为值v。可以用于动态地为对象添加属性或者修改已有属性的值。如果属性不存在,则会创建一个新的属性;如果属性已经存在,则会修改属性的值。
例如,以下示例代码演示了使用setattr()函数修改或创建对象的属性:
class MyClass:pass# 创建对象
my_obj = MyClass()# 修改属性的值
setattr(my_obj, 'name', 'John')
print(my_obj.name) # 输出: John# 创建新的属性
setattr(my_obj, 'age', 25)
print(my_obj.age) # 输出: 25
在上述示例中,通过调用setattr()函数为my_obj对象添加了两个属性:name和age。第一个setattr()函数会修改my_obj对象的name属性的值为'John',第二个setattr()函数会在my_obj对象中创建一个新的age属性,并将其值设置为25。
如果你能灵活掌握这两章的内容并且熟悉unittest的源码,懂suite的构建,你便可以手撸一套测试框架出来。
因为,httprunner在底层改为go语言之前,便是采用的suite概念。
HttpRunner的数据驱动功能也是通过自定义元类来实现的。元类可以动态地对测试用例类或测试步骤进行修改,实现不同的数据输入或参数组合。
好了,后续我也会更新go语言!
相关文章:
元类在测试框架中的运用
元类在测试框架中的运用 书接上回 我们知道了元类的基本用法,也写了一个小demo,接下来我们就尝试运用进我们测试框架。 #一款无需编码且易用于二次开发的接口测试框架。 #我写的我写的我写的我写的 pip install mwj-apitest #这里面就用到了元类&…...
VBA快速交叉分段标记字符颜色
实例需求:A列中有不确定行数的数据,现在需要将数据按照每4位一组间隔标记颜色,如下图所示。 示例代码如下。 Sub Demo()Dim rngCell As RangeDim rngData As RangeDim i, res, intLenSet rngData Range("A1").CurrentRegionrngDa…...
根据Pytorch源码实现的 ResNet18
一,类模块定义: import torch import torch.nn as nn import torch.nn.functional as F from torch import Tensorclass ResBlock(nn.Module):def __init__(self, inchannel, outchannel, stride1) -> None:super(ResBlock, self).__init__()# 这里定义了残差块…...
药品管理系统servlet+jsp+sql医院药店仓库进销存java源代码mysql
本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 药品管理系统servletjspsql 系统有1权限:…...
这9个UI设计工具一定码住!非常好用
对于设计师来说,好用的UI设计工具无疑会对设计工作起到事半功倍的作用,今天本文与大家分享9个好用的UI设计工具,一起来看看吧! 1、即时设计 即时设计是一个能在网页中直接使用,且支持团队协作的国产UI设计工具&#…...
gin通过反射来执行动态的方法
在gin中,可以通过反射来执行对应的方法。下面是一个示例: package mainimport ("fmt""github.com/gin-gonic/gin""reflect" )type UserController struct{}func (uc *UserController) GetUser(c *gin.Context) {userId :…...
java高并发系列 - 第23天:JUC中原子类,一篇就够了
java高并发系列 - 第23天:JUC中原子类 这是java高并发系列第23篇文章,环境:jdk1.8。 本文主要内容 JUC中的原子类介绍介绍基本类型原子类介绍数组类型原子类介绍引用类型原子类介绍对象属性修改相关原子类预备知识 JUC中的原子类都是都是依靠volatile、CAS、Unsafe类配合…...
《HeadFirst设计模式(第二版)》第一章源码
代码文件目录结构: FlyBehavior.java package Chapter1_StrategyPattern.ch1_3_behavior.behaviors.fly;public interface FlyBehavior {void fly(); } FlyNoWay.java package Chapter1_StrategyPattern.ch1_3_behavior.behaviors.fly;public class FlyNoWay imp…...
insert into select用法
文章目录 一、insert into select二、insert into select插入失败 本篇文章主要讲解insert into select 的用法,以及insert into select的坑或者注意事项。本篇文章中的sql基于mysql8.0进行讲解 一、insert into select 该语法常用于从另一张表查询数据插入到某表中…...
图像识别技术:计算机视觉的进化与应用展望
导言: 图像识别技术是计算机视觉领域的重要研究方向,它使计算机能够理解和解释图像内容,从而实现自动化和智能化的图像处理。随着深度学习等技术的快速发展,图像识别在诸多领域取得了重大突破,如自动驾驶、医疗影像分析…...
【免费送书】重新定义Python学习!
欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。关…...
Qt 4. 发布exe
把ex2.exe放在H盘Ex2文件夹下,执行 H:\Ex2>windeployqt ex2.exe H:\Ex2>windeployqt ex2.exe H:\Ex2\ex2.exe 64 bit, release executable Adding Qt5Svg for qsvgicon.dll Skipping plugin qtvirtualkeyboardplugin.dll due to disabled dependencies (Qt5…...
消息队列的使用场景以及优缺点
消息队列是一种在应用系统之间传递消息的通信模式。它允许发送者将消息发布到一个队列中,而接收者则从队列中获取消息进行处理。 消息队列的主要特点包括: 异步通信:消息的发送和接收是异步进行的,发送者无需等待接收者的即时响应…...
掌握Python的X篇_17_循环语句(while;for var in ;range)
文章目录 1. 为什么需要循环2. while循环3. for...in循环4. range函数 1. 为什么需要循环 循环语句方便我们做重复的事情,比如: for i in range (0,3):print("重要的事情说三遍")运行效果如下: Python中有while循环和for循环两…...
IDEA maven 报错 malformed \uxxx encoding
IDEA maven 报错 malformed \uxxx encoding 最近搞几个JAVA项目总是出现上面错误,在网上搜的大部分都是删maven库,删jar包等等,每次都搞了好久才解决,今天无意中发现并不是包的问题, 解决办法 1.点击 idea 右侧的ma…...
Django实现音乐网站 ⑵
使用Python Django框架制作一个音乐网站,在系列文章1的基础上继续开发,本篇主要是后台歌手表模块开发。 目录 表结构设计 歌手表(singer)结构 创建表模型 设置图片上传路径 创建上传文件目录 生成表迁移 执行创建表 后台管…...
Vue 基础语法(二)
一、背景: 我们对于基础语法,说白了就是实现元素赋值,循环,判断,以及事件响应即可! 二、v-bind 我们已经成功创建了第一个 Vue 应用!看起来这跟渲染一个字符串模板非常类似,但是 V…...
kafka raft协议
1、首先要了解kafka是什么(Scala) Kafka是一个分布式的消息订阅系统,消息被持久化到一个topic中,topic是按照“主题名-分区”存储的,一个topic可以分为多个partition,在parition(分区)内的每条消息都有一个有序的id号,这个id号被称为偏移(offset),记录消息的消息位置…...
平板光波导中导模的(注意不是泄露模)传播常数β的matlab计算(验证了是对的)
参照的是导波光学_王建(清华大学)的公式(3-1-2、3-1-3),算的参数是这本书的图3-3的。 function []PropagationConstantsMain() clear;clc;close all lambda01.55;%真空或空气中的入射波长,单位um k02*pi/lambda0; m3;%导模阶数(需要人为指定) n11.62;%芯…...
JVM面试题--JVM组成
JVM是什么 Java Virtual Machine Java程序的运行环境(java二进制字节码的运行环境) 运行流程 什么是程序计数器? 程序计数器:线程私有的,内部保存的字节码的行号。用于记录正在执行的字节码指令的地址。 我们知道ja…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
RLHF vs RLVR:对齐学习中的两种强化方式详解
在语言模型对齐(alignment)中,强化学习(RL)是一种重要的策略。而其中两种典型形式——RLHF(Reinforcement Learning with Human Feedback) 与 RLVR(Reinforcement Learning with Ver…...
C/Python/Go示例 | Socket Programing与RPC
Socket Programming介绍 Computer networking这个领域围绕着两台电脑或者同一台电脑内的不同进程之间的数据传输和信息交流,会涉及到许多有意思的话题,诸如怎么确保对方能收到信息,怎么应对数据丢失、被污染或者顺序混乱,怎么提高…...
Windows开机自动启动中间件
WinSW(Windows Service Wrapper 是一个开源的 Windows 服务包装器,它可以帮助你将应用程序打包成系统服务,并实现开机自启动的功能。 一、下载 WinSW 下载 WinSW-x64.exe v2.12.0 (⬇️ 更多版本下载) 和 sample-minimal.xml 二、配置 WinS…...
