接口自动化pytest+request+allure+logging+yaml+ddddocr验证码识别

本文主要是介绍接口自动化pytest+request+allure+logging+yaml+ddddocr验证码识别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、封装工具类common

fixture夹具

import pytest
from common.yaml_util import YamlUtil@pytest.fixture(scope='session',autouse=True)
def excute_sql():#print("连接数据库")YamlUtil().clean_yaml()#清空extract.yaml文件中的token、useridyield #print("测试执行什么")#作用是控制执行用例中执行什么# print("关闭数据库")

图像识别

(demo中暂时未使用,实际测试效果差强人意)此处加了一些自己图片处理逻辑,可以按照实际情况来修改逻辑;pyocr效果没有这个好

import os
import time
from PIL import Image
import ddddocr
import requestsdef returncode():re1=requests.request(method='get',url='http://localhost:8081/api/checkCode')# print(re1)with open(os.getcwd()+'\images\ceshi1.jpg',mode='wb') as f:f.write(re1.content)# 打开图片文件image = Image.open(os.getcwd()+"\images\ceshi1.jpg")# 将图像转换为灰度图像# gray_image = ImageOps.grayscale(image)# gray_image.show()# 转换为黑白二值图像,调整阈值以减少噪声和干扰,# 直接降噪,不灰度处理binary_image = image.point(lambda x: x < 200 and 255)binary_image.save(os.getcwd()+'\images\ceshi2.jpg')time.sleep(3)# 显示处理后的图像# binary_image.show()with open(os.getcwd()+'images\ceshi2.jpg','rb') as f:img=f.read()ocr=ddddocr.DdddOcr()result=ocr.classification(img)return result

封装请求、日志、接口关联数据操作、断言

需要按照实际场景进行微小修改

import loggingimport jsonpath
import requests
import json
from common.yaml_util import YamlUtil
from builtins import str
import reclass RequestUtil:def __init__(self, two_node):self.base_url = YamlUtil().read_config('base', two_node)# 替换值的方法# #(替换url,params,data,json,headers)# #(string,int,float,list,dict)def replace_value(self, data):if data:# 保存数据类型data_type = type(data)# 判断数据类型转换成strif isinstance(data, dict) or isinstance(data, list):str_data = json.dumps(data)else:str_data = str(data)for cs in range(1, str_data.count('${') + 1):# 替换if "${" in str_data and "}" in str_data:start_index = str_data.index("${")end_index = str_data.index("}", start_index)old_value = str_data[start_index:end_index + 1]new_value = YamlUtil().red_yaml(old_value[2:-1])str_data = str_data.replace(old_value, str(new_value))# 还原数据类型if isinstance(data, dict) or isinstance(data, list):data = json.loads(str_data)else:data = data_type(str_data)return data# 规范yaml测试用例def standard_yaml(self, caseinfo):caseinfo_keys = caseinfo.keys()# 判断一级关键字是否包含:name,request,validateif "name" in caseinfo_keys and "request" in caseinfo_keys and "validate" in caseinfo_keys:# 判断request下面是否包含:method、urlrequest_keys = caseinfo["request"].keys()if "method" in request_keys and "url" in request_keys:print("yaml基本架构检查通过")logging.debug(msg="{}请求信息:{}".format(caseinfo["title"],caseinfo["request"]))method = caseinfo['request'].pop("method")  # pop() 函数用于移除列表中的一个元素,并且返回该元素的值。url = caseinfo['request'].pop("url")res = self.send_request(method, url, **caseinfo['request'])  # caseinfo需要解包加**return_text = res.textlogging.debug(msg="{}响应信息:".format(caseinfo["title"]) + res.text)return_code = res.status_codereturn_json = ""try:return_json = res.json()except Exception as e:print("extract返回的结果不是JSON格式")# 提取值并写入extract.yaml文件if "extract" in caseinfo.keys():for key, value in caseinfo["extract"].items():if "(.*?)" in value or "(.+?)" in value:  # 正则表达式zz_value = re.search(value, return_text)if zz_value:extract_value = {key: zz_value.group(1)}YamlUtil().write_yaml(extract_value)else:  # jsonpathresturn_json = res.json()js_value = jsonpath.jsonpath(resturn_json, value)if js_value:extract_value = {key: js_value[0]}YamlUtil().write_yaml(extract_value)# 断言:logging.debug(msg="{}断言信息:{}".format(caseinfo["title"],caseinfo["validate"]))self.assert_result(caseinfo['validate'], return_json, return_code)return reselse:print("在request下必须包含method,url")else:print("一级关键字必须包含name,request,validate")sess = requests.session()# 统一请求封装def send_request(self, method, url, **kwargs):method = str(method).lower()  # 转换小写# 基础路径的拼接和替换url = self.base_url + self.replace_value(url)print(url)# 参数替换for key, value in kwargs.items():if key in ['params', 'data', 'json', 'headers','url']:kwargs[key] = self.replace_value(value)elif key == "files":for file_key, file_path in value.items():value[file_key] = open(file_path, 'rb')res = RequestUtil.sess.request(method, url, **kwargs)return res# 断言def assert_result(self, yq_result, sj_result, return_code):all_flag = 0for yq in yq_result:for key, value in yq.items():print(key, value)if key == "equals":flag = self.equals_assert(value, return_code, sj_result)all_flag = all_flag + flagelif key == 'contains':flag = self.contains_assert(value, sj_result)all_flag = all_flag + flagelse:print("框架暂不支持此段断言方式")assert all_flag == 0 , logging.debug(msg="Failed")# 相等断言def equals_assert(self, value, return_code, sj_result):flag = 0for assert_key, assert_value in value.items():print(assert_key, assert_value)if assert_key == "status_code":  # 状态断言if assert_value != return_code:flag = flag + 1print("断言失败,返回的状态码不等于%s" % assert_value)else:lists = jsonpath.jsonpath(sj_result, '$..%s' % assert_key)if lists:if assert_value not in lists:flag = flag + 1print("断言失败:" + assert_key + "不等于" + str(assert_value))else:flag = flag + 1print("断言失败:返回的结果不存在:" + assert_key)return flag# 包含断言def contains_assert(self, value, sj_result):flag = 0if value not in str(sj_result):flag = flag + 1print("断言失败:返回的结果中不包含:" + value)return flag

封装yaml文件操作方法

extract.yaml文件是存在接口关联的数据,提取的数据

import osimport yamlclass YamlUtil:
# 读def red_yaml(self,key):with open(os.getcwd() + '/extract.yaml', mode='r', encoding='utf-8') as f:value = yaml.load(f, yaml.FullLoader)return value[key]# 写def write_yaml(self,data):with open(os.getcwd() + '/extract.yaml', mode='a+', encoding='utf-8') as f:yaml.dump(data, stream=f, allow_unicode=True)# 清空def clean_yaml(self):with open(os.getcwd() + '/extract.yaml', mode='w', encoding='utf-8') as f:f.truncate()# 读yaml文件def read_yamlfile(slef,file):with open(os.getcwd() + '/' + file, mode='r', encoding='utf-8') as f:value = yaml.load(f, yaml.FullLoader)return valuedef read_config(self,one_node,two_node):with open(os.getcwd() + '/config.yaml', mode='r', encoding='utf-8') as f:value = yaml.load(f, yaml.FullLoader)return value[one_node][two_node]

2、配置文件

编辑环境控制yaml文件

base:base_test_url: http://testbase_normal_url: https://***

编辑pytest.ini文件

[pytest]
log_cli = true
log_cli_level = DEBUG
log_cli_format = %(asctime)s %(levelname)s %(message)s %(filename)s
log_file = ./log/test.log
log_file_level = DEBUG
log_date_format = %Y-%m-%d %H:%M:%S
log_file_format = %(asctime)s %(levelname)s %(message)s %(filename)s
log_file_date_format = %Y-%m-%d %H:%M:%S;addopts = -sv -m "smoke" --reruns 2 -n 2 --html=./reports/report3.html --capture=sys
addopts = -sv --alluredir=./tmps --clean-alluredir
testpaths = ./testcases
python_files = test_*.py
python_classes = Test_*
python_functions = test_*
markers=smoke:冒烟测试

3、编写测试用例以及执行文件

编写测试用例

import allure
from common.conftest import *
from common.yaml_util import YamlUtil
from common.request_url import RequestUtilclass Test_ap:@allure.feature("登录")@allure.story("登录接口")@pytest.mark.smoke@pytest.mark.parametrize("caseinfo",YamlUtil().read_yamlfile("testcases/test_login.yaml"))def test_login(self,excute_sql,caseinfo):print(excute_sql)# Yamlutil().write_yaml(excute_sql)res = RequestUtil("base_test_url").standard_yaml(caseinfo)@allure.feature("用户管理")@allure.story("用户管理接口")@pytest.mark.smoke@pytest.mark.parametrize("caseinfo",YamlUtil().read_yamlfile("testcases/test_curd_user.yaml"))def test_adduser(self,excute_sql,caseinfo):print(excute_sql)# Yamlutil().write_yaml(excute_sql)res = RequestUtil("base_test_url").standard_yaml(caseinfo)

编写执行文件

import os
import timeimport pytestif __name__ == '__main__':pytest.main(['-sv','--html=./reports/report.html'])time.sleep(4)os.system("allure generate ./tmps -o ./reportsallure --clean")

编写登录yaml测试数据;存在提取token

-featrue: 登录story: 登录接口title: 不存在账户登录name: 1request:method: posturl: /api/auth/oauth/tokendata:username: admin1password: e85ce909a38157c2fcgrant_type: passwordclient_id: hmcclient_secret: 123456validate:- equals: {status_code: 200}- contains: "用户名不存在"
-featrue: 登录story: 登录接口title: 正常登录name: 1request:method: posturl: /api/auth/oauth/tokendata:username: adminpassword: e85ce909a38157c2fcb022grant_type: passwordclient_id: hmcclient_secret: 123456extract:access_token: $.data.access_tokenvalidate:- equals: {status_code: 200}- contains: "OK"

编写用户增删改查(curd)测试用例数据。存在提取userid此处需要注意yaml文件的编写方式

-name: 1feature: 管理用户story: 新增用户title: 新增用户接口request:url: /api/system/user/addmethod: postjson: {"deptId":"12","userName":"testsa","nickName":"test","roleId":3,"deptType":0}headers:"Content-Type": "application/json""Authorization": "Bearer ${access_token}"validate:- equals: {status_code: 200}- contains: "OK"-name: 1feature: 管理用户story: 查询用户title: 查询用户接口request:url: /api/system/user/loadListmethod: postjson: {"pageNum":1,"pageSize":10,"username":"testsa"}headers:"Content-Type": "application/json""Authorization": "Bearer ${access_token}"validate:- equals: {status_code: 200}- contains: "OK"extract:userid: "$.data.list.[0].userId"-name: 1feature: 管理用户story: 修改用户title: 修改用户接口request:url: /api/system/user/editmethod: PUTjson:"userId": ${userid}"deptId": "12""userName": "testsa""nickName": "test""roleId": 3"remark": nullheaders:"Content-Type": "application/json""Authorization": "Bearer ${access_token}"validate:- equals: {status_code: 200}- contains: "OK"-name: 1feature: 管理用户story: 删除用户title: 删除用户接口request:url: /api/system/user/${userid}method: deleteheaders:"Content-Type": "application/json""Authorization": "Bearer ${access_token}"validate:- equals: {status_code: 200}- contains: "OK"

4、实际效果展示

代码结构截图:

日志:

 pytest-html:

 allure报告:

后续可以自行安排将代码上传gitlab,联动jenkins;jenkins环境需要先部署好所有需要的环境和库

这篇关于接口自动化pytest+request+allure+logging+yaml+ddddocr验证码识别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/219984

相关文章

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

如何使用Ansible实现CI/CD流水线的自动化

如何使用Ansible实现CI/CD流水线的自动化 持续集成(CI)和持续交付(CD)是现代软件开发过程中的核心实践,它们帮助团队更快地交付高质量的软件。Ansible,作为一个强大的自动化工具,可以在CI/CD流水线中发挥关键作用。本文将详细介绍如何使用Ansible实现CI/CD流水线的自动化,包括设计流水线的结构、配置管理、自动化测试、部署、以及集成Ansible与CI/CD工具(如Jen

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

Spring 验证码(kaptcha)

首先引入需要的jar包: <dependency><groupId>com.github.axet</groupId><artifactId>kaptcha</artifactId><version>0.0.9</version></dependency> 配置验证码相关设置: <bean id="captchaProducer" class="com.

java线程深度解析(一)——java new 接口?匿名内部类给你答案

http://blog.csdn.net/daybreak1209/article/details/51305477 一、内部类 1、内部类初识 一般,一个类里主要包含类的方法和属性,但在Java中还提出在类中继续定义类(内部类)的概念。 内部类的定义:类的内部定义类 先来看一个实例 [html]  view plain copy pu

模拟实现vector中的常见接口

insert void insert(iterator pos, const T& x){if (_finish == _endofstorage){int n = pos - _start;size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;reserve(newcapacity);pos = _start + n;//防止迭代

京东物流查询|开发者调用API接口实现

快递聚合查询的优势 1、高效整合多种快递信息。2、实时动态更新。3、自动化管理流程。 聚合国内外1500家快递公司的物流信息查询服务,使用API接口查询京东物流的便捷步骤,首先选择专业的数据平台的快递API接口:物流快递查询API接口-单号查询API - 探数数据 以下示例是参考的示例代码: import requestsurl = "http://api.tanshuapi.com/a

ImportError: cannot import name ‘print_log‘ from ‘logging‘

mmcv升级到2.+后删除了很多 解决 查FAQ文档,找到 添加到mmcv.utils下即可

图解可观测Metrics, tracing, and logging

最近在看Gophercon大会PPT的时候无意中看到了关于Metrics,Tracing和Logging相关的一篇文章,凑巧这些我基本都接触过,也是去年后半年到现在一直在做和研究的东西。从去年的关于Metrics的goappmonitor,到今年在排查问题时脑洞的基于log全链路(Tracing)追踪系统的设计,正好是对这三个话题的实践。这不禁让我对它们的关系进行思考:Metrics和Loggi