当前位置: 首页 > news >正文

自动化测试之httprunner框架hook函数实操

本篇介绍httprunner中hook函数的使用,以及通过编程能力实现建设自动化测试更全面的场景覆盖


前置:

互联网时代让我们更快的学习到什么是Httprunner

正文:

        经过上文了解到这个框架怎么使用之后,我们开始来探讨一下我们为什么要用hook函数?用hook函数能帮我们实现什么?能给我们带来什么收益?

举个例子:假设我们的业务系统目前是通过Kafka来实现消息的交互,A系统生产的消息B系统需要去消费处理后在生产消息给到下游系统

那么如果说我们需要为B系统编写这类流程的自动化,我们需要怎么实现呢?

一)设计

首先考虑一个问题:如果A系统是独立系统,如果我们写的自动化要依赖A系统的数据那就耦合度太高了。如果我们只考虑B系统的完整性,那么我们完全可以把A mock掉,将A生产的报文消息当作cases,通过python脚本来实现。

然后B系统消费后会操作数据库,那么我们断言是否可以也读数据库去判断是否预期

其次B会发消息来通知下游系统消费,那么我们是不是也可以写一个kafka监听消费消息,判断报文是否符合预期

二)实现

1、先写一个发送消息的函数,这个地方加一个参数是为了写多个cases

import json
from kafka import KafkaProducerdef sengMessage(tag):producer = KafkaProducer(bootstrap_servers='这个地方写集群名称')if('A' == tag):msg_dict = {"CMD": "这个地方是CMD","Data": "这个地方是消息体","Key": "这个是Key","LogID": "681533193628954414","Tag": "这个是标识","TimeStamp": "这是个时间","Topic": "这是个要发送的主题"}msg = json.dumps(msg_dict).encode()#partition这个地方写的是0表示放0这个Partition上了,如果要随机就看你有几个Partition,random一下producer.send("这个地方放主题topic", msg, partition=0)producer.close()

2、然后将这个函数放到debugtalk.py文件里面

3、编写一个cases,将此函数引用到setup_hooks

使用方式就是${函数名称(参数)},说明一下就是为啥要在setup_hooks里面使用,是因为需要在执行cases之前将消息发送之后系统消费到了才能走后面的流程(就是前置)

然后这个前置操作可以做:消息的发送、数据的处理(比如删除数据,更新数据等等)

4、编写一个操作数据库的函数

import pymysql
import yaml
from loguru import logger
from lib import utilsclass MySQL(object):"""Mysql数据库操作"""db = {}def __init__(self, db):"""初始化数据库对象Args:db (str): 数据库名字,代表了db配置的某个文件,数据库连接信息也在对应文件配置"""file = f"{utils.get_root_path()}/conf/{db}.yml"with open(file, encoding="utf-8") as conf:self.db = yaml.load(conf, Loader=yaml.FullLoader)def execute(self, sql):"""在mysql上执行一个sql语句,返回的结果为多条记录的元组,每条记录为dict,内容为字段-值字典Returns:[tuple]: 执行结果"""self.db['cursorclass'] = pymysql.cursors.DictCursortry:connection = pymysql.connect(**self.db)logger.info(f"execute sql: [{sql}]")with connection.cursor() as cursor:cursor.execute(sql)data = cursor.fetchall()logger.debug(f"execute ret: [{data}]")connection.commit()finally:connection.close()return data
#怎么使用呢,就是直接用这个函数传配置文件名称,sql
if __name__ == '__main__':MySQL("auto").execute("select * from A limit 1")

设置放置存储数据库配置文件的目录

数据库配置

host: IP
port: 端口
user: 用户名
passwd: 密码
db: 数据库

5、能操作数据库之后,那么我们是否可以将查询回来的全部重要字段(什么自增主键ID、时间啥的就不用断言了)进行判断了,写一个比较json的函数

class Check(object):def CheckSql(prama):db = 'auto'errmsgl_success = 'success'sql = 'SELECT A,B,C,D,E,F,G,H,I,J,K from AAA where aa=' + '\'' + str(prama) + '\''sql_count = 'SELECT count(1) from AAA  WHERE (aa = ' + "\'" + str(prama) + "\'" + ')'# 先查询条数,没有就重试,如果重试还没有就失败count = MySQL(db).execute(sql_count)[0]['count(1)']retry = 0while count == 0 and retry < 15:time.sleep(3)retry = retry + 1count = MySQL(db).execute(sql_count)[0]['count(1)']aa = MySQL(db).execute(sql)[0]response = json.dumps(aa)print(response)# 这个地方,假如A字段是一个JSON,这个地方是做了一个处理,让这个json排序,就不会出现每次查询这个json都是乱序得导致断言失败# 假设A字段:[{fee:1},{fee:2},{fee:3}],那么我们就用fee来排序A = eval(str(aa["A"]))aa["A"] = sorted(A, key=lambda x: (x['fee']), reverse=True)print(json.dumps(aa))# 这个地方用的直接是传进来得参数作为文件名称checkfile__detail = str(prama) detail_ret = Check.checkfile_json(aa, checkfile__detail)if detail_ret != errmsgl_success:return '文件名称:' + checkfile__detail + ', 失败原因: ' + detail_retreturn errmsgl_success# 读取对应的预期文件,这个函数可以抽出来,当一个公共方法def checkfile_json(requestdata, checkfile):# 文件地址当前项目/checkfile/checkfile.jsonbasic_url = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '/checkfile'if checkfile:with open(basic_url + checkfile + '.json', 'r') as f:setdatas = json.load(f)return Check.cmp(requestdata, setdatas)def cmp(src_data, dst_data):msg = 'success'if isinstance(dst_data, dict):"""若为dict格式"""for key in dst_data:if key not in src_data:return 'key: ' + str(key) + ' 在请求中不存在'msg = Check.cmp(src_data[key], dst_data[key])if msg != 'success':return msgelif isinstance(dst_data, list):"""若为list格式"""for src_list, dst_list in zip((src_data), (dst_data)):"""递归"""msg = Check.cmp(src_list, dst_list)if msg != 'success':return msgelse:if str(src_data) != str(dst_data):return 'src_data != dst_data, src_data: ' + str(src_data) + ', dst_data: ' + str(dst_data)return msg

6、断言函数既然已经写好了,那就直接引用,同上面那个流程,加载到debugtaik.py文件之后,我们需要在cases断言处加上此函数,还是用${函数名称(参数)}来引用

7、最后编写一下消费kafka消息进行断言的函数

    def check_kafka_messgae(topic, bootstrap_servers, checkfile, enable_auto_commit=False, consumer_timeout_ms=300):# 参数分别是主题,集群,断言文件地址,自动提交,超时时间consumer = KafkaConsumer(bootstrap_servers=[bootstrap_servers], enable_auto_commit=enable_auto_commit,consumer_timeout_ms=consumer_timeout_ms)# 这个地方只监听一个partition == 0的topic_partition = TopicPartition(topic=topic, partition=0)lastoffset = consumer.end_offsets([topic_partition])[topic_partition]consumer.assign([topic_partition])consumer.seek(topic_partition, lastoffset - 1)messagelist = ''for message in consumer:messagelist = message.valuemessagelist = json.loads(json.loads(str(messagelist, 'utf-8'))['Data'])print('topic数据' + str(messagelist))# checkfile_json这个方法上面写得函数里面有,直接调用return checkfile_json(messagelist, checkfile)

8、同上,还是将这个函数加入到debugtaik.py,在validate里面进行断言判断

总结:

将上面的流程串起来之后发现,从kafak消息的发送、数据库的查询、文件读取/数据判断,到kafka消息监听断言整个流程能够完成上述的诉求。

通过一个例子来解读hook函数的作用。在真实的业务场景下,我们在编写自动化cases的时候完全可以用纯代码的方式来实现我的复杂的业务场景。通过这种方式能更有效的认可自动化去替代人工操作。


后话:

个人认为自动化的灵魂不是用什么工具,而是断言。不管是人工还是程序自动操作都需要有一个判断依据,如果这个判断依据十分有效,那么我们只需要完善场景cases就能实现自动化替换人工(百分之80吧)

相关文章:

自动化测试之httprunner框架hook函数实操

本篇介绍httprunner中hook函数的使用&#xff0c;以及通过编程能力实现建设自动化测试更全面的场景覆盖 前置&#xff1a; 互联网时代让我们更快的学习到什么是Httprunner 正文&#xff1a; 经过上文了解到这个框架怎么使用之后&#xff0c;我们开始来探讨一下我们为什么要用…...

物联网实战--入门篇之(七)嵌入式-MQTT

目录 一、MQTT简介 二、MQTT使用方法 三、MQTT驱动设计 四、代码解析 五、使用过程 六、总结 一、MQTT简介 MQTT因为其轻量、高效和稳定的特点&#xff0c;特别适合作为物联网系统的数据传输协议&#xff0c;已经成为物联网事实上的通信标准了。关于协议的具体内容看看这…...

跑模型——labelme的json文件转成yolo使用的txt文件(语义分割)

前言 将labelme多边形标注的json文件转换成yolo使用的txt文件 import os import json import numpy as np from tqdm import tqdm#实现函数 def json2txt(path_json, path_txt): # 可修改生成格式with open(path_json, r) as path_json:jsonx json.load(path_json)with open…...

一个项目仿京东商场代码

git clone http://git.itcast.cn/heimaqianduan/erabbit-uni-app-vue3-ts.git...

计算机网络——WEB服务器编程实验

实验目的 1. 处理一个 http 请求 2. 接收并解析 http 请求 3. 从服务器文件系统中获得被请求的文件 4. 创建一个包括被请求的文件的 http 响应信息 5. 直接发送该信息到客户端 具体内容 一、C 程序来实现 web 服务器功能。 二、用 HTML 语言编写两个 HTML文件&#xff0c;并…...

蓝桥杯算法题:最大比例

题目描述&#xff1a; X星球的某个大奖赛设了 M 级奖励。 每个级别的奖金是一个正整数。 并且&#xff0c;相邻的两个级别间的比例是个固定值。 也就是说&#xff1a;所有级别的奖金数构成了一个等比数列。 比如&#xff1a;16,24,36,54&#xff0c;其等比值为&#xff1a;3/2。…...

【堡垒机】堡垒机的介绍

目前&#xff0c;常用的堡垒机有收费和开源两类。 收费的有行云管家、纽盾堡垒机&#xff1b; 开源的有jumpserver&#xff1b; 这几种各有各的优缺点&#xff0c;如何选择&#xff0c;大家可以根据实际场景来判断 什么是堡垒机 堡垒机&#xff0c;即在一个特定的网络环境下&…...

通过 ffmpeg命令行 调节视频播放速度

1. 仅调整视频速率 视频调速原理&#xff1a;修改视频的pts&#xff0c;dts # 可能会丢帧 ffmpeg -i input.mkv -an -filter:v "setpts0.5*PTS" output.mkv # 可用-r参数指定输出视频FPS以防止丢帧 ffmpeg -i input.mkv -an -r 60 -filter:v "setpts2.0*PTS&q…...

SQLite数据库在Linux系统上的使用

SQLite是一个轻量级的数据库解决方案&#xff0c;它是一个嵌入式的数据库管理系统。SQLite的特点是无需独立的服务器进程&#xff0c;可以直接嵌入到使用它的应用程序中。由于其配置简单、支持跨平台、服务器零管理&#xff0c;以及不需要复杂的设置和操作&#xff0c;SQLite非…...

Spring中依赖注入的方法有几种,分别是什么?

依赖注入的目的&#xff1a; 都是为了减少对象之间的紧密耦合 1. 构造函数注入&#xff1a;通过在类的构造函数中接受依赖对象作为参数&#xff0c;Spring在创建对象时将依赖注入。 2. Setter方法注入&#xff1a;在类中提供setter方法&#xff0c;Spring通过调用这些setter方法…...

【面试精讲】MyBatis设计模式及源码分析,MyBatis设计模式实现原理

【面试精讲】MyBatis设计模式及源码分析&#xff0c;MyBatis设计模式实现原理 目录 本文导读 一、MyBatis中运用的设计模式详解 1. 工厂模式&#xff08;Factory Pattern&#xff09; 2. 单例模式&#xff08;Singleton Pattern&#xff09; 3. 建造者模式&#xff08;Bu…...

Acrel-1000DP光伏监控系统在尚雷仕(湖北)健康科技有限公司5.98MW分布式光伏10KV并网系统的应用

摘 要&#xff1a;分布式光伏发电特指在用户场地附近建设&#xff0c;运行方式多为自发自用&#xff0c;余电上网&#xff0c;部分项目采用全额上网模式。分布式光伏全额上网的优点是可以充分利用分布式光伏发电系统的发电量&#xff0c;提高分布式光伏发电系统的利用率。发展分…...

电脑远程控制esp32上的LED

1、思路整理 首先esp32需要连接上wifi 然后创建udp socket 接受udp数据 最后解析数据&#xff0c;控制LED 2、micropython代码实现 import network from socket import * from machine import Pin p2Pin(2,Pin.OUT)def do_connect(): #连接wifi wlan network.WLAN(network.…...

ARXML处理 - C#的解析代码(一)

目的 本文介绍通过AUTOSAR组织提供的xsd文件&#xff0c;自动生成对应的C#解析代码的框架。 自动生成方法&#xff1a;Microsoft SDKs\Windows\v7.0A\bin\xsd.exe 命令&#xff1a;xsd.exe AUTOSAR_4-0-3.xsd /c /l:CS /n:AUTOSAR4 AUTOSAR_4-0-3.xsd 是需要生成代码的xsd文…...

OJ 栓奶牛【C】【Python】【二分算法】

题目 算法思路 要求的距离在最近木桩与最远木桩相隔距离到零之间&#xff0c;所以是二分法 先取一个中间值&#xff0c;看按照这个中间值可以栓多少奶牛&#xff0c;再与输入奶牛数比较&#xff0c;如果大于等于&#xff0c;则增大距离&#xff0c;注意这里等于也是增大距离…...

Spring6-单元测试:JUnit

1. 概念 在进行单元测试时&#xff0c;特别是针对使用了Spring框架的应用程序&#xff0c;我们通常需要与Spring容器交互以获取被测试对象及其依赖。传统做法是在每个测试方法中手动创建Spring容器并从中获取所需的Bean。以下面的两行常见代码为例&#xff1a; ApplicationCo…...

ubuntu系统安装k8s1.28精简步骤

目录 一、规划二、环境准备2.1 配置apt仓库配置系统基本软件仓库配置k8s软件仓库安装常用软件包 2.2 修改静态ip、ntp时间同步、主机名、hosts文件、主机免密2.3 内核配置2.4 关闭防火墙、selinux、swap2.5 安装软件安装docker安装containerd安装k8s软件包 三、安装配置k8s3.1 …...

探讨Java和Go语言的缺点

文章目录 Java的缺点Go语言的缺点 通常我们都会讨论Java和GO的优点&#xff0c;如果讨论缺点往往能让人们更清楚优点的重要性&#xff0c;Java和Go的缺点或许往往就是对方优点所在 Java的缺点 冗长的代码&#xff1a;相较于一些现代编程语言&#xff0c;Java 的语法相对冗长&am…...

短剧在线搜索PHP网站源码

源码简介 短剧在线搜索PHP网站源码&#xff0c;自带本地数据库500数据&#xff0c;共有6000短剧视频&#xff0c;与短剧猫一样。 搭建环境 PHP 7.3 Mysql 5.6 安装教程 1.上传源码到网站目录中 2.修改【admin.php】中&#xff0c; $username ‘后台登录账号’; $passwor…...

Python map遍历

在Python中&#xff0c;map 函数是一个内置函数&#xff0c;它将指定的函数应用于给定序列&#xff08;如列表、元组等&#xff09;的每个项&#xff0c;并返回一个迭代器&#xff0c;该迭代器包含所有项经过指定函数处理后的结果。 ### map 函数的基本用法 map 函数的语法如…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...