pytest+requests+allure自动化测试接入Jenkins学习

🍅 视频学习:文末有免费的配套视频可观看

🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快

最近在这整理知识,发现在pytest的知识文档缺少系统性,这里整理一下,方便后续回忆。

在python中,大家比较熟悉的两个框架是unittest和pytest:

Unittest是Python标准库中自带的单元测试框架,Unittest有时候也被称为PyUnit,就像JUnit是Java语言的标准单元测试框架一样,Unittest则是Python语言的标准单元测试框架。

Pytest是Python的另一个第三方单元测试库。它的目的是让单元测试变得更容易,并且也能扩展到支持应用层面复杂的功能测试。

两者之间的区别如下:

在这里插入图片描述

这里试用的pytest框架,加上request来实现接口自动化的测试,整个框架考虑到使用数据驱动的方式,将数据维护在Excel文档中。

1、下载安装allure

下载地址:

https://github.com/allure-framework/allure2/releases

https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/

选择需要的版本下载,这里我下载的是2.13.2版本

下载好后,解压到你需要存放的路目录,并配置环境变量

在这里插入图片描述

检查是否配置成功,执行cmd,输入命令 allure,出现如下图,则表示安装成功

图片

2、下载安装python

下载地址https://www.python.org/

下载好后,安装并配置环境变量,具体流程可以网络查找

3、python安装依赖包

cmd命令执行,也可以通过项目中的requirements.txt来安装,安装步骤后面再说

pip3 install allure-pytest
pip3 install pytest
pip3 install pytest_html
pip3 install request

4、下载并安装pycharm工具

查看网络教程

5、在pycharm,新建项目及编码

图片

项目目录如图:

  • base:存放一些最底层的方法封装,协议,请求发送等。
  • common:存放一些公共方法。
  • config:存放配置文件。
  • testData:存放测试数据。
  • log:存放日志。
  • report:存放报告。
  • testCase:存放用例。
  • utils:存放公共类。
  • readme:用于说明文档。
  • requirements.txt:用于记录所有依赖包极其版本号,便于环境部署,可以通过pip命令自动生成和安装

图片

这里采用数据驱动的方式,数据通过读取excel文件来执行测试,所以这里需要封装读取excel的方法,使用xlrd来操作读取

# operationExcel.py
import jsonfrom common.contentsManage import filePath
import xlrd, xlwt
class OperationExcel:# 获取shell表def getSheet(self, index=0):book = xlrd.open_workbook(filePath())return book.sheet_by_index(index) #根据索引获取到sheet表# 以列表形式读取出所有数据def getExcelData(self, index=0):data = []sheet = self.getSheet(index=index)title = sheet.row_values(0) # (0)获取第一行也就是表头for row in range(1, sheet.nrows): # 从第二行开始获取row_value = sheet.row_values(row)data.append(dict(zip(title, row_value))) # 将读取出第一条用例作为一个字典存放近列表return data# 对excel表头进行全局变量定义
class ExcelVarles:case_Id = "用例ID"case_module="用例模块"case_name="用例名称"case_server="用例地址"case_url="请求地址"case_method="请求方法"case_type="请求类型"case_data="请求参数"case_headers="请求头"case_preposition="前置条件"case_isRun = "是否执行"case_code = "状态码"case_result = "期望结果"if __name__ == "__main__":opExcel = OperationExcel()# opExcel.getSheet()# print(opExcel.getExcelData())opExcel.writeExcelData(1, 7, f"test{2}")

excel 文件内容如图

图片

封装用例

# test_api_all.py
# 参数化运用所有用例
import json
import pytestfrom utils.operationExcel import OperationExcel, ExcelVarles
from base.method import ApiRequest
from common.log import loggeropExcel = OperationExcel()
apiRequest = ApiRequest()@pytest.mark.parametrize('data', opExcel.getExcelData()) # 装饰器进行封装用例
def test_api(data, login_token=None):if data[ExcelVarles.case_isRun] == "N" :logger.info("跳过执行用例")return# 请求头作为空处理并添加tokenheaders = data[ExcelVarles.case_headers]if len(str(headers).split()) == 0:passelif len(str(headers).split()) >= 0:headers = json.loads(headers) # 转换为字典#     headers['Authorization'] = login_token # 获取登录返回的token并添加到读取出来的headers里面headers = headers# 对请求参数做为空处理params = data[ExcelVarles.case_data]if len(str(params).split()) == 0:passelif len(str(params).split()) == 0:params = paramsurl = data[ExcelVarles.case_server] + data[ExcelVarles.case_url] + "?" + paramsr = apiRequest.all_method( data[ExcelVarles.case_method] ,url, headers=headers)logger.info(f"响应结果{r}")responseResult = json.loads(r)case_result_assert(data[ExcelVarles.case_code], responseResult['code'])# 断言封装
def case_result_assert(expectedResult, actualReuls) :'''断言封装:param expectedResult: 预期结果:param actualReuls: 实际结果:return:'''assert expectedResult == actualReuls # 状态码

封装日志文件

# log.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import logging
import time
import osfrom common.contentsManage import logDir# BASE_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
# # 定义日志文件路径
# LOG_PATH = os.path.join(BASE_PATH, "log")
# if not os.path.exists(LOG_PATH):
#     os.mkdir(LOG_PATH)# 方法1
# 封装自己的logging
class MyLogger:def __init__(self):self._logName = os.path.join(logDir(), "{}.log".format(time.strftime("%Y%m%d")))self._logger = logging.getLogger("logger")self._logger.setLevel(logging.DEBUG)self._formatter = logging.Formatter('[%(asctime)s][%(filename)s %(lineno)d][%(levelname)s]:%(message)s')self._streamHandler = logging.StreamHandler()self._fileHandler = logging.FileHandler(self._logName, mode='a', encoding="utf-8")self._streamHandler.setFormatter(self._formatter)self._fileHandler.setFormatter(self._formatter)self._logger.addHandler(self._streamHandler)self._logger.addHandler(self._fileHandler)# 获取logger日志记录器def get_logger(self):return self._loggerlogger = MyLogger().get_logger()

封装请求方法

# method.py
import json
import requests
from common.log import logger
from utils.commonUtils import isJsonclass ApiRequest(object):# ---- 第一种请求方式封装requests库,调用可根据实际情况传参 ----# def send_requests(self, method, url, data=None, params=None, headers=None,#                   cookies=None,json=None,files=None,auth=None,timeout=None,#                   proxies=None,verify=None,cert=None):#     self.res = requestes.request(method=method, url= url, headers=headers,data=data,#                                params=params, cookies=cookies,json = json,files=files,#                                auth=auth, timeout= timeout, proxies=proxies,verify=verify,#                                cert=cert)#     return self.res# 第二种封装方法def get(self, url, data=None, headers=None, payload=None):if headers is not None:res = requests.get(url=url, data=data,headers=headers)else:res = requests.get(url=url, data=data)return resdef post(self, url, data, headers, payload:dict, files=None):if headers is not None:res = requests.post(url=url, data=data, headers=headers)else :res = requests.post(url=url, data=data)if str(res) == "<Response [200]>" :return res.json()else :return res.textdef put(self,url,data,headers, payload:dict, files=None):if headers is not None :res = requests.put(url=url,data=data,headers=headers)else:res = requests.put(url=url,data=data)return resdef delete(self,url,data,headers, payload:dict):if headers is not None :res = requests.delete(url=url,data=data,headers=headers)else:res = requests.delete(url=url,data=data)return resdef all_method(self, method, url, data=None, headers=None, payload=None, files=None):logger.info(f"请求方法是{method}, 请求地址{url}")if headers == None:headers = {}if method.upper()=='GET':res = self.get(url,data,headers, payload)elif method.upper()=='POST':res = self.post(url, data, headers, payload, files)elif method.upper() == 'PUT':res = self.put(url, data, headers, payload, files)elif method.upper() == 'DELETE':res = self.delete(url, data, headers, payload)else :res = f'请求{method}方式不支持,或者不正确'return json.dumps(res, ensure_ascii=False, indent=4, sort_keys=True, separators=(',',':'))

运行

# run.py
import shutil
import pytest
import osfrom common.log import logger
import subprocess # 通过标准库中的subprocess包来fork一个子进程,并运行一个外部的程序
from common.contentsManage import htmlDir, resultDirif __name__ == '__main__':htmlPath = htmlDir()resultPath = resultDir()if os.path.exists(resultPath) and os.path.isdir(resultPath):logger.info("清理上一次执行的结果")shutil.rmtree(resultPath, True)logger.info("开始测试")pytest.main(["-s", "-v", "--alluredir", resultPath]) #运行输出并在resport/result目录下生成json文件logger.info("结束测试")# 如果是代码单独执行,需要立马看到报告,可以执行下面语句,如果配合Jenkins使用,则可以不需要执行,Jenkins自带的插件allure会操作# logger.info("生成报告")# subprocess.call('allure generate ' + resultPath + ' -o '+ htmlPath +' --clean', shell=True) # 读取json文件并生成html报告,--clean诺目录存在则先清楚# logger.info("查看报告")# subprocess.call('allure open -h 127.0.0.1 -p 9999 '+htmlPath+'', shell=True) #生成一个本地的服务并自动打开html报告

依赖包安装,可以执行命令 pip3 install -r requirements.txt,来安装

# requirements.txt
pytest==7.4.3
pytest-html==4.1.1
pytest-xdist==3.5.0
pytest-ordering==0.6
pytest-rerunfailures==13.0
allure-pytest==2.13.2
xlrd==1.2.0
requests==2.31.0

至此,项目的代码框架就基本结束了

6、安装并配置Jenkins

Jenkins的安装,看你需要在Windows还是Linux下安装,具体教程可以网络查找

Jenkins安装allure插件

图片

Jenkins安装并登录后,可以创建任务

图片

图片

图片

添加构建步骤,根据你安装环境的不同,选择不同的构建

图片

图片

添加构建后操作,选择 allure Report

图片

配置代码执行的结果地址

图片

运行测试后,可以在任务中查看allure生成的报告

图片

图片

至此,jenkins+python+pytest+requests+allure的接口自动化测试就记录到这里,刚兴趣的可以去看看pytest的官方文档,了解更多知识。

同时,在这我为大家准备了一份软件测试视频教程(含面试、接口、自动化、性能测试等),就在下方,需要的可以直接去观看。

字节大佬,一周讲完,自动化测试项目实战,这套教程是怎么称霸B站的?【2024最新版】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/852825.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

陕西移动联合中兴通讯,赋能5G RedCap智慧工厂建设

前不久&#xff0c;陕西移动联合中兴通讯、高新兴等产业伙伴在中兴通讯西安智能终端生产基地顺利完成5G RedCap在智慧工厂的应用实践。本次实践证明了5G RedCap在智慧工厂场景下的应用可行性&#xff0c;为RedCap在工业智能制造行业的应用打下基础。   5G RedCap技术是5G-A实现…

【cocos creator 3.x】 修改builtin-unlit 加了一个类似流光显示的mask参数

效果见图&#xff1a; shader 代码修改如下&#xff0c; 主要看 USE_MASK_UVY 关键字部分修改&#xff1a; // Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd. CCEffect %{techniques:- name: opaquepasses:- vert: unlit-vs:vertfrag: unlit-fs:fragproperties: &a…

Linux-centos7 nvm使用

NVM下载使用 文件夹创建拉取nvm包在~/.bashrc的末尾&#xff0c;添加如下语句验证nvm是否安装成功 文件夹创建 mkdir /root/home/software/拉取nvm包 cd /root/home/software/ wget https://github.com/nvm-sh/nvm/archive/refs/tags/v0.38.0.tar.gz tar xvzf v0.38.0.tar.g…

MyBatis-Plus整合达梦数据库

文章目录 1. 环境准备2. 创建Spring Boot项目3. 引入依赖4. 配置数据源5. 配置MyBatis-Plus6. 创建实体类7. 创建Mapper接口8. 创建Service类9. 创建Controller类10. 创建Mapper XML文件11. 测试12. 进一步优化12.1 配置分页插件12.2 配置乐观锁插件13. 总结🎉欢迎来到Java学…

【Linux】常见指令的使用

文章目录 which指令stat 指令wc指令echo指令tree 指令whoami指令clear指令alias指令ls指令pwd指令cd 指令touch指令mkdir指令&#xff08;重要&#xff09;rmdir指令 && rm 指令&#xff08;重要&#xff09;man指令&#xff08;重要&#xff09;cp指令&#xff08;重要…

Java课程设计:基于swing的贪吃蛇小游戏

文章目录 一、项目介绍二、核心代码三、项目展示四、源码获取 一、项目介绍 贪吃蛇是一款经典的休闲益智游戏,自问世以来便深受广大用户的喜爱。这个游戏的基本玩法是控制一条不断增长的蛇,目标是吃掉屏幕上出现的食物,同时避免撞到边缘或自身。随着游戏的进行,蛇的身体会越长…

Burp Suite使用及BruteForc_test靶场实战

简介 Burp Suite是用于攻击和测试Web应用程序安全性的集成平台&#xff0c;包含多个协同工作的工具&#xff0c;支持信息共享与复杂攻击。设计有加速攻击流程的接口&#xff0c;所有工具共享强大框架&#xff0c;处理HTTP消息、持久性、认证、代理、日志和警报。主要用于安全性…

grpc代理服务的实现(一)

最近公司需要无感知基于服务代号来实现通信, 并监控和管理通信连接&#xff0c;目前公司使用的是如下的逻辑(当然逻辑简化了&#xff0c;但是思想不变) 目录 简单的原理图代理服务的实现创建 tls tcp 服务, 用于grpc client 和 grpc service 通信保存 与 代理服务建立的 grpc …

Codeforces Round 926 (Div. 2)(A~C题解)

A题是个签到题&#xff0c;BC思维题目&#xff0c;搞出来结论就秒了&#xff0c;D题是个树上DP由于现在水平薄弱还没做出来&#xff0c;以后补上 A. Sasha and the Beautiful Array 思路给数组排序&#xff0c;然后后项减前项&#xff0c;累加值就是最终结果&#xff0c;签到题…

AI 大模型的赛点:通用与垂直之争

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

短视频矩阵源码---矩阵托管1000个账号如何正规开发规则实现

一、短视频矩阵源码开发实现规则&#xff1a; 1.首先是确保各个官方平台api接口的稳定性&#xff0c;一定要是各个平台正规的api 2.其次是保证服务器运行&#xff0c;带宽保证能够并行&#xff0c;目前我们这边用的是源码所需服务器配置&#xff1a;规格:最低8核16G2、硬盘:系…

GIS之arcgis系列10:arcpy实现批量掩膜提取

按掩膜提取 (Spatial Analyst) 提取掩膜所定义区域内的相应栅格像元。 OutRas ExtractByMask(InRas1, InMsk1, "INSIDE") 使用情况 输入栅格中的其他属性&#xff08;若有的话&#xff09;将按照原样添加到输出栅格属性表。 根据所记录的属性&#xff0c;某些属性…

【NLP练习】Transformer中的位置编码

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、什么是位置编码 1. 位置编码定义 Transformer 模型中的位置编码是为了在处理序列数据时引入位置信息&#xff0c;以便模型能够分辨输入序列中不同位置的词…

蓝卓为中小制造企业注入数字化转型活力

随着劳动力成本上升,原材料价格上涨,企业生产成本逐年增加&#xff0c;市场竞争越来越激烈&#xff0c;传统的中小制造企业面临着巨大的压力。 通过数字化转型应对环境的变化已成为行业共识&#xff0c;在数字化的进程中&#xff0c;中小企业首要考虑生存问题&#xff0c;不能…

Kubernetes集群持久化部署实践

WordPress 网站持久化部署 要持久化MariaDB 可以把 Deployment 改成了 StatefulSet&#xff0c;修改 YAML添加“serviceName”“volumeClaimTemplates”这两个字段&#xff0c;定义网络标识和 NFS 动态存储卷&#xff0c;然后在容器部分用“volumeMounts”挂载到容器里的数据目…

八 、VS的调试技巧

--- 24.4.20 目录 1、什么是Bug&#xff1f; 2、什么是调试&#xff08;Debug&#xff09;&#xff1f; 3、Debug和Release 4、VS基础调试快捷键 4.1、环境准备 4.2、调试快捷键 5、监视和内存观察 5.1、监视窗口 5.2、内存窗口 6、调试举例1 7、调试举例2 8、调试…

旅行者1号有什么秘密?飞行240多亿公里,为什么没发生碰撞?

旅行者1号有什么秘密&#xff1f;飞行240多亿公里&#xff0c;为什么没发生碰撞&#xff1f; 自古以来&#xff0c;人类就对浩瀚无垠的宇宙充满了好奇与向往。从最初的仰望星空&#xff0c;到如今的深空探测&#xff0c;人类探测宇宙的历史发展可谓是一部波澜壮阔的史诗。 在…

双指针练习:有效三角形的个数

题目链接&#xff1a;611.有效三角形的个数 题目描述&#xff1a; 给定一个包含非负整数的数组 nums &#xff0c;返回其中可以组成三角形三条边的三元组个数。 解法一&#xff08;暴力求解&#xff09;&#xff08;会超时&#xff09;&#xff1a; 算法思路&#xff1a; 三层…

Chromium源码阅读:从页面加载到元素展示(1)

​ 从&#xff1c;p&#xff1e;hello world&#xff1c;/p&#xff1e;.html到界面上的hello world 今天&#xff0c;我们一起来看看一个html元素&#xff0c;是如何绘制到界面上。我们选择了最简单的场景&#xff0c;便于快速掌握总体的流程&#xff0c;加深之前阅读知识的…

yolo模型评估指标相关概念

mAP&#xff08;mean Average Precision 平均精度&#xff09;&#xff0c;是一个经常被用来衡量目标 检测模型是否具有较好性能的指标。 计算mAP需要先计算每一类物体的AP&#xff0c;然后取平均值&#xff0c;所以下面介绍的 TP,FP,FN,TN都是针对某一类物体&#xff08;目标&…