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

测开新手: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的官方文档,了解更多知识。

行动吧,在路上总比一直观望的要好,未来的你肯定会感谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入群: 1007119548,里面有各种测试开发资料和技术可以一起交流哦。

最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取 【保证100%免费】

在这里插入图片描述

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。在这里插入图片描述
在这里插入图片描述在这里插入图片描述

相关文章:

测开新手:pytest+requests+allure自动化测试接入Jenkins学习

最近在这整理知识&#xff0c;发现在pytest的知识文档缺少系统性&#xff0c;这里整理一下&#xff0c;方便后续回忆。 在python中&#xff0c;大家比较熟悉的两个框架是unittest和pytest&#xff1a; Unittest是Python标准库中自带的单元测试框架&#xff0c;Unittest有时候…...

学习网络编程No.11【传输层协议之UDP】

引言&#xff1a; 北京时间&#xff1a;2023/11/20/9:17&#xff0c;昨天成功更文&#xff0c;上周实现了更文两篇&#xff0c;所以这周再接再厉。当然做题任在继续&#xff0c;而目前做题给我的感觉以套路和技巧偏多&#xff0c;还是那句话很多东西不经历你就是不懂&#xff…...

向爬虫而生---Redis 基石篇6 <拓展HyperLogLog>

前言: 继续之前的 向爬虫而生---Redis 基石篇5 &#xff1c;拓展Zset&#xff1e;-CSDN博客 一些比较基础的redis类型在初中级阶段用着没有毛病,但是到了大数据时代,慢慢一些更高级的场景,就需要把这几个类型搬出来了! 正文: 概念: 当我们需要对一个大型数据集进行去重计…...

JavaScript中的this

在实际应用中&#xff0c;了解 this 的行为是非常重要的&#xff0c;特别是在编写库或框架时&#xff0c;或者当你需要在回调函数中访问特定的上下文时&#xff0c;通常推荐使用箭头函数或者其他方法来确保 this 的正确指向。 在ES6中&#xff0c;this 的值取决于它是如何被调用…...

宝塔php站点设置伪静态规则 访问 a.com 时候跳转到 a.com/b.html

要在宝塔 PHP 站点中设置伪静态规则&#xff0c;实现访问a.com时跳转到a.com/b.html&#xff0c;可以按照以下步骤进行操作&#xff1a; 打开宝塔面板并登录到你的服务器管理界面。进入网站设置页面&#xff0c;找到你要设置伪静态规则的 PHP 站点。在站点设置中&#xff0c;找…...

git介绍4.2

git(版本控制工具) 一、git 介绍 1、git是目前世界上最先进的分布式版本控制系统&#xff0c;可以有效&#xff0c;高速的处理从小到大的项目版本管理。 2、git是linux torvalds 为了帮助管理linux内核开发二开发的一个开放源码的版本控制软件。 3、git作用&#xff1a;更好…...

【深入了解设计模式】组合设计模式

组合设计模式 组合模式是一种结构型设计模式&#xff0c;它允许你将对象组合成树状结构来表现“整体-部分”关系。组合模式使得客户端可以统一对待单个对象和组合对象&#xff0c;从而使得代码更加灵活和易于扩展。 概述 ​ 对于这个图片肯定会非常熟悉&#xff0c;上图我们可…...

4.Java---方法+重载

方法 方法的调用是需要开辟内存的,方法调用结束内存就被销毁了. 下面将介绍一个经典的错误标准的0分的示意! 我们日常中写交换两个数字的代码的时候都会用如下的方法进行描述: 你是不是觉得自己写的特别对!终于可以独立写一个小小的函数了? 下面运行一下看看结果 哦莫!怎么…...

蓝桥杯Java B组历年真题(2013年-2021年)

一、2013年真题 1、世纪末的星期 使用日期类判断就行&#xff0c;这里使用LocalDate&#xff0c;也可以使用Calendar类 答案 2099 使用LocalDate import java.time.LocalDate; import java.time.format.DateTimeFormatter; // 1:无需package // 2: 类名必须Main, 不可修改p…...

C++笔记(五)--- 虚函数(virtual)

目录 虚函数介绍 虚函数、覆盖和重载区别 虚函数介绍 C的虚函数是多态性的表现 1.构造函数不能为虚函数2.子类继承时虚函数仍为虚函数3.虚函数类外实现时&#xff0c;不需要加virtual4.有虚函数的类&#xff0c;析构函数一定要写成虚函数&#xff08;否则可能会造成内存泄漏&…...

编写加密程序,加密规则为:将所有字母转化为该字母后的第三个字母,即A->D、B->E

编写加密程序&#xff0c;加密规则为&#xff1a;将所有字母转化为该字母后的第三个字母&#xff0c;即A->D、B->E、C->F、…、Y->B、Z->C。小写字母同上&#xff0c;其他字符不做转化。输入任意字符串&#xff0c;输出加密后的结果。 例如&#xff1a;输入&qu…...

【笔记】:更方便的将一个List中的数据传入另一个List中,避免多重循环

这里是 simpleInfoList 集合&#xff0c;记为集合A&#xff08;传值对象&#xff09; List<CourseSimpleInfoDTO> simpleInfoList courseClient.getSimpleInfoList(courseIds);if(simpleInfoListnull){throw new BizIllegalException("当前课程不存在!");}这…...

Cisco Secure ACS 5.8.0.32 安装 + Crack 教程

Cisco Secure ACS 5.8.0.32 安装 Crack 教程 前言系统环境开始安装 开始破解导入授权文件 前言 在ESXi 6.7 上经历过无数次的安装尝试 测试了各种兼容版本都没有安装成功,记最后一次安装成功的过程. 系统环境 服务器 : Dell R720xd CPU : E5-2620 v2 系统 : ESXi 6.7…...

项目准备March

Nginx主要用来作为Http服务器&#xff0c;要实现Tomcat的负载均衡&#xff0c;就可以通过Nginx来实现。 正向代理代理的是客户端&#xff0c;反向代理代理的是服务端。SpringBoot采用约定优于配置的思想&#xff0c;简化Spring项目的配置开发。 前端请求其实并未直接发送到后…...

集智书童 | YOLO+混合注意力机制 | YOLOv5再加4.3%才可以做对手,Transformer混合设计依旧可以卷

本文来源公众号“集智书童”&#xff0c;侵权删&#xff0c;干货满满。YOLOv5重出江湖&#xff01; 原文链接&#xff1a;https://mp.weixin.qq.com/s/vb7HsA0fKDgRc3uC8Z-2yw 在工业生产过程中&#xff0c;由于低效率、不统一的评估、高成本以及缺乏实时数据&#xff0c;传统…...

Codeforces Round 894 (Div. 3)----->C. Flower City Fence

题目总思路&#xff1a; 要判断是否对称&#xff0c;只需要判断两个放法得到的图形是否相同&#xff08;竖着放&#xff0c;横着放&#xff09;&#xff0c;这两个放法有个很重要的特性&#xff1a;就是数组中大于1的个数&#xff0c;就是横着放时&#xff0c;第一竖排的高度。…...

CryoEM - CryoAI: Amortized Inference of Poses 工程源码复现

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/136384544 Paper: CryoAI: Amortized Inference of Poses for Ab Initio Reconstruction of 3D Molecular Volumes from Real Cryo-EM Images CryoAI: 基于摊…...

项目预备知识

导入两个头文件 #include <graphics.h> // 引入 EasyX 的图形库头文件 #include <conio.h> // 引入 conio.h 以使用 getch() 窗口创建函数&#xff1a;小黑屏 initgraph(640, 480, SHOWCONSOLE); closegraph(); //关闭一个窗口 设置背景颜色&#xff1a;这…...

redis实战笔记汇总

文章目录 1 NoSQL入门概述1.1 能干嘛&#xff1f;1.2 传统RDBMS VS NOSQL1.3 NoSQL数据库的四大分类1.4 分布式数据库CAP原理 BASE原则1.5 分布式集群简介1.6 淘宝商品信息的存储方案 2 Redis入门概述2.1 是什么&#xff1f;2.2 能干嘛&#xff1f;2.3 怎么玩&#xff1f;核心…...

elment-ui table表格排序后 清除排序箭头/恢复默认排序 的高亮样式

问题描述&#xff1a; 1.默认排序是按照名称升序排列&#xff08;图一&#xff09; 2.在选择了筛选项以及其他排序方式之后&#xff0c;箭头高亮是这样的&#xff08;图二&#xff09; 3.当我点击清空按钮后&#xff0c;类型清空了&#xff0c;并且传给后端的排序方式是名称/升…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...