从0到1框架搭建,Python+Pytest+Allure+Git+Jenkins接口自动化框架(超细整理)

目录:导读

    • 前言
    • 一、Python编程入门到精通
    • 二、接口自动化项目实战
    • 三、Web自动化项目实战
    • 四、App自动化项目实战
    • 五、一线大厂简历
    • 六、测试开发DevOps体系
    • 七、常用自动化测试工具
    • 八、JMeter性能测试
    • 九、总结(尾部小惊喜)


前言

接口测试是对系统和组件之间的接口进行测试,主要是效验数据的交换,传递和控制管理过程,以及相互逻辑依赖关系。其中接口协议分为HTTP,RPC,Webservice,Dubbo,RESTful等类型。

接口测试流程
1、需求评审,熟悉业务和需求
2、开发提供接口文档
3、编写接口测试用例
4、用例评审
5、提测后开始测试
6、提交测试报告

两种常见的 HTTP 请求方法:GET 和 POST

框架是一套基于Python+Pytest+Requests+Allure+Jenkins而设计的数据驱动接口自动化测试的框架。

技术栈:
Python、Pytest、Requests、Pactverity、Excel、Json、Mysql、Allure、Logbook、Git、Jenkins

框架结构图:

B1

项目功能:
Python+Pytest+Allure+Jenkins接口自动化框架,实现Excel或Json维护测试用例,支持数据库操作,利用封装的请求基类调取相应的测试用例接口,获取配置文件中的环境地址与环境变量,

结合Pytest进行单元测试,使用LogBook进行记录日志,并生成allure测试报告,最后进行Jenkins集成项目实现集成部署,并发送测试报告邮件。

工具类封装

1、日志模块
项目中的log日志是logbook进行日志记录的,方便测试开发调试时进行排错纠正或修复优化。日志可选择是否打印在屏幕上即运行时是否在终端输出打印。日志格式输出可调整。

handle_log.py部分源码

 def log_type(record, handler):log = "[{date}] [{level}] [{filename}] [{func_name}] [{lineno}] {msg}".format(date=record.time,  # 日志时间level=record.level_name,  # 日志等级filename=os.path.split(record.filename)[-1],  # 文件名func_name=record.func_name,  # 函数名lineno=record.lineno,  # 行号msg=record.message  # 日志内容)return log# 日志存放路径LOG_DIR = BasePath + '/log'print(LOG_DIR)if not os.path.exists(LOG_DIR):os.makedirs(LOG_DIR)# 日志打印到屏幕log_std = ColorizedStderrHandler(bubble=True)log_std.formatter = log_type# 日志打印到文件log_file = TimedRotatingFileHandler(os.path.join(LOG_DIR, '%s.log' % 'log'), date_format='%Y-%m-%d', bubble=True, encoding='utf-8')log_file.formatter = log_type# 脚本日志run_log = Logger("global_log")def init_logger():logbook.set_datetime_format("local")run_log.handlers = []run_log.handlers.append(log_file)run_log.handlers.append(log_std)return ""

打印在终端的日志,如下图所示。

B2

同时运行项目后,会在项目文件log中自动生成一个以当天日期命名的log文件。点击log日志文件可查看日志详情即项目运行时所记录的日志或报错日志。如下图所示。

B3

2、配置文件模块
项目中涉及到一些配置文件如username、password或环境变量时,我们可通过配置文件来获取配置值。通过配置文件中key与value的定义来确定获取配置文件的值。

handle_init.py部分源码

 class HandleInit:# 读取配置文件def load_ini(self):file_path = BasePath + "/config/config.ini"cf = configparser.ConfigParser()cf.read(file_path, encoding='UTF-8')return cf# 获取ini里面对应key的valuedef get_value(self, key, node=None):if node == None:node = 'Test'cf = self.load_ini()try:data = cf.get(node, key)logger.info('获取配置文件的值,node:{},key:{}, data:{}'.format(node, key, data))except Exception:logger.exception('没有获取到对应的值,node:{},key:{}'.format(node, key))data = Nonereturn data

获取配置文件中的值日志如下图所示。

B3

3、接口请求封装
获取相关测试用例及接口用例配置,记录请求相关参数的日志,定义Allure测试报告的步骤。

handle_apirequest.py部分代码

class ApiRequest:def api_request(self, base_url, test_case_data, case_data):get_name = Noneget_url = Noneget_method = Noneget_headers = Noneget_cookies = Noneget_case_name = Noneget_case_params = Noneresponse_data = Nonetry:get_name = test_case_data['config']['name']get_url = base_url + test_case_data['config']['url']get_method = test_case_data['config']['method']get_headers = test_case_data['config']['headers']get_cookies = test_case_data['config']['cookies']except Exception as e:logger.exception('获取用例基本信息失败,{}'.format(e))try:get_case_name = case_data['name']get_case_params = case_data['params']except Exception as e:logger.exception('获取测试用例信息失败,{}'.format(e))with allure.step("请求接口:%s,请求地址:%s,请求方法:%s,请求头:%s,请求Cookies:%s" % (get_name, get_url, get_method, get_headers, get_cookies)):allure.attach("接口用例描述:", "{0}".format(get_case_name))allure.attach("接口用例请求参数:", "{0}".format(get_case_params))logger.info('请求接口名:%r,请求地址:%r,请求方法:%r,请求头:%r,请求Cookies:%r' %\ (get_name, get_url, get_method, get_headers, get_cookies))logger.info('请求接口名:%r,请求接口用例名:%r,接口用例请求参数:%r' %\(get_name, get_case_name, get_case_params))try:response_data = baseRequest.run_main(get_method, get_url, get_case_params, get_headers)except Exception as e:logger.exception('用例请求返回失败,{}'.format(e))logger.info('请求接口名:%r,请求接口用例名:%r,返回参数:%r' % (get_name, get_case_name, response_data.json()))return response_data

4、Excel数据处理-测试用例

B4

测试用例中维护在Excel文件中,类中定义如何获取Excel中的相关数据(如获取某个单元格的内容,获取单元格的行数,以及将数据写入Excel中等操作)。

handle_exceldata.py部分源码

class OperationExcel:def __init__(self, file_name=None, sheet_id=None):if file_name:self.file_name = file_nameself.sheet_id = sheet_idelse:self.file_name = ''self.sheet_id = 0self.data = self.get_data()# 获取sheets的内容def get_data(self):data = xlrd.open_workbook(self.file_name)tables = data.sheets()[self.sheet_id]return tables# 获取单元格的行数def get_lines(self):tables = self.datareturn tables.nrows# 获取某一个单元格的内容def get_cell_value(self, row, col):return self.data.cell_value(row, col)

5、JSON数据处理-测试用例

{"config":{"name":"post接口名","url":"/langdetect","method":"POST","headers":{"Content-Type":"application/json"},"cookies":{}},"testcase":[{"name":"测试用例1","params":{"query":"测试"},"validate":[{"check":"status_code","comparator":"eq","expect":"200"}]},{"name":"测试用例2","params":{"query":"python"},"validate":[{"check":"msg","comparator":"eq","expect":"success"}]}]
}

获取Json文件中里具体字段的值。
handle.json.py部分源码

class HandleJson:# 读取json文件def load_json(self, file_name):if file_name == None:file_path = ""else:file_path = file_nametry:with open(file_path, encoding='UTF-8') as f:data = json.load(f)return dataexcept Exception:print("未找到json文件")return {}# 读取json文件里具体的字段值def getJson_value(self, key, file_name):if file_name == None:return ""jsonData = self.load_json(file_name)if key == None:getJsonValue = ""else:getJsonValue = jsonData.get(key)return getJsonValue

基类封装

接口支持Get、Post请求,调用requests请求来实现接口的调用与返回。接口参数包括,接口地址、接口请求参数、cookie参数、header参数。

class BaseRequest:def send_get(self, url, data, header=None, cookie=None):"""Requests发送Get请求:param url:请求地址:param data:Get请求参数:param cookie:cookie参数:param header:header参数"""response = requests.get(url=url, params=data, cookies=cookie, headers=header)return responsedef send_post(self, url, data, header=None, cookie=None):"""Requests发送Post请求:param url:请求地址:param data:Post请求参数:param data:Post请求参数:param cookie:cookie参数:param header:header参数"""response = requests.post(url=url, json=data, cookies=cookie, headers=header)return response# 主函数调用def run_main(self, method, url, data, header, cookie=None):try:result = ''if method.upper() == 'GET':result = self.send_get(url, data, header, cookie)elif method.upper() == 'POST':result = self.send_post(url, data, header, cookie)return resultexcept Exception as e:logger.exception('请求主函数调用失败:{}'.format(e))

测试用例编写

引用Pytest来进行接口的单元测试,通过JSON中多个测试用例来做为参数化数据驱动。结合Allure制定相应接口的测试报告。在接口返回断言之前,我们先进行该接口的契约测试,

我们采用的是Pactverity的全量契约校验测试。当契约测试通过时,我们再进行返回参数的相关校验测试。

test_getRequestJson.py部分源码

@allure.feature('测试GET请求模块')
class TestRequestOne():@allure.title('测试标题')@allure.testcase('测试地址:https://www.imooc.com')@pytest.mark.parametrize('case_data', testCaseData['testcase'])def test_requestOne(self, case_data):try:api_response = apiRequest.api_request(baseurl, testCaseData, case_data)api_response_data = api_response.json()# pactverity——全量契约校验config_contract_format = Like({"msg": "成功","result": 0,"data": EachLike({"word": Like("testng")})})mPactVerify = PactVerify(config_contract_format)try:mPactVerify.verify(api_response_data)logger.info('verify_result:{},verify_info:{}'.format(mPactVerify.verify_result, mPactVerify.verify_info))assert mPactVerify.verify_result == Trueexcept Exception:err_msg = '契约校验错误'logger.exception('测试用例契约校验失败,verify_result:{},verify_info:{}'.format(mPactVerify.verify_result,mPactVerify.verify_info))try:for case_validate in case_data['validate']:logger.info('断言期望相关参数:check:{},comparator:{},expect:{}'.format(case_validate['check'],case_validate['comparator'],case_validate['expect']))comparatorsTest.comparators_Assert(api_response, case_validate['check'],case_validate['comparator'], case_validate['expect'])logger.info('测试用例断言成功')except Exception as e:logger.exception('测试用例断言失败')except Exception as e:logger.exception('测试用例请求失败,原因:{}'.format(e))

主运行:

运用Pytest和Allure的特性,命令行运行测试用例文件夹,并生成对应的allure测试报告。

if __name__ == "__main__":pytest.main(['-s', '-v', 'test_case/testRequest/', '-q', '--alluredir', 'reports'])

Alluer2 测试报告

当我们运行主函数时,并生成对应的测试用例报告时,我们可以看到在该文件夹中会生成对应的json文件的测试报告。

reports是json格式测试报告存放的目录位置,allure_reports是html测试报告文件生成的目录位置。allure命令如下。

allure generate reports -o allure_result/

项目根目录下的allure_reports文件,存放的是allure生成的测试报告。可看出文件下有一个HTML文件,可通过Python的编辑器Pycharm来打开该HTML文件(测试报告),或可通过allure命令来打开该HTML。

下面是我整理的2023年最全的软件测试工程师学习知识架构体系图

一、Python编程入门到精通

请添加图片描述

二、接口自动化项目实战

请添加图片描述

三、Web自动化项目实战

请添加图片描述

四、App自动化项目实战

请添加图片描述

五、一线大厂简历

请添加图片描述

六、测试开发DevOps体系

请添加图片描述

七、常用自动化测试工具

请添加图片描述

八、JMeter性能测试

请添加图片描述

九、总结(尾部小惊喜)

勇攀高峰,永不言弃,奋斗的旅程犹如绽放的花朵;跨越征程,超越极限,拼搏的力量铸就辉煌的人生。相信自己的潜能,释放内心的火焰,用汗水和努力砥砺出属于自己的辉煌之路。

披荆斩棘,破浪前行,奋斗是人生最壮丽的交响乐;勇往直前,超越极限,梦想是心灵最美的翅膀。相信坚持,追逐光芒,奋斗点亮未来的星空,谱写属于自己的辉煌篇章。

不畏艰辛,奋斗向前,执着追寻心中的星辰大海;拥抱挑战,超越极限,每一次努力都是成长的脚印。相信自己的力量,燃烧激情,创造出属于自己的辉煌人生。

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

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

相关文章

将word每页页眉单独设置

在进行论文排版的时候,总是会出现页眉的页码设置问题,比如出现奇数或偶数页码一致,尝试将前面页码改掉,后面再修改前面也进行了变动,将每页页眉单独设置: (1)在第一页的最后一行输入…

【雕爷学编程】MicroPython动手做(29)——物联网之SIoT

知识点:什么是掌控板? 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片,支持WiFi和蓝牙双模通信,可作为物联网节点,实现物联网应用。同时掌控板上集成了OLED…

【2023年电赛】运动目标控制与自动追踪系统(E 题)最简单实现

本方案的思路是最简单的不涉及复杂算法:识别矩形框,标记矩形框,输出坐标和中心点,计算长度,控制舵机移动固定长度!仅供完成基础功能参考,不喜勿喷! # 实现运动目标控制与自动追踪系…

企业上云实施路线图

企业上云步骤主要分为规划、设计、实施、验证、运维五个阶段。https://articles.e-works.net.cn/cloud/article144684.htm

JVM基础篇-直接内存

JVM基础篇-直接内存 什么是直接内存? 直接内存( 堆外内存 ) 指的是 Java 应用程序通过直接方式从操作系统中申请的内存,这块内存不属于jvm 传统方式读取文件 首先会从用户态切换到内核态,调用操作系统函数从磁盘读取文件,读取一部分到操作系统缓冲区…

Azure pipeline自动化打包发布

pipeline自动化,提交代码后,就自动打包,打包成功后自动发布 第一步 pipeline提交代码后,自动打包。 1 在Repos,分支里选择要触发的分支,这里选择cn_china,对该分支设置分支策略 2 在生产验证中增加新的策略 3 在分支安…

2023华数杯数学建模C题完整论文,包括每个问题的代码

目录 摘要 2.1 问题 1 的问题分析 2.2 问题 2 的问题分析 2.3 问题 3 的问题分析 完成版论文见此 摘要 问题一,我们使用了390名3至12个月婴儿及其母亲的相关数据,探讨了母亲的 身体和心理指标对婴儿的行为特征和睡眠质量的影响。我们首先进行了描述…

【JavaEE初阶】博客系统后端

文章目录 一. 创建项目 引入依赖二. 设计数据库三. 编写数据库代码四. 创建实体类五. 封装数据库的增删查改六. 具体功能书写1. 博客列表页2. 博客详情页3. 博客登录页4. 检测登录状态5. 实现显示用户信息的功能6. 退出登录状态7. 发布博客 一. 创建项目 引入依赖 创建blog_sy…

Dockerfile构建lamp镜像

1、构建目录 [rootdocker ~]# mkdir compose_lamp [rootdocker ~]# cd compose_lamp/ 2、编写Docekerfile [rootdocker compose_lamp]# vim Dockerfile #基础镜像 FROM centos:7#维护该镜像的用户信息 MAINTAINER Crushlinux <crushlinux163.com>#安装httpd RUN yum -…

LEARNING TO EXPLORE USING ACTIVE NEURAL SLAM 论文阅读

论文信息 题目&#xff1a;LEARNING TO EXPLORE USING ACTIVE NEURAL SLAM 作者&#xff1a;Devendra Singh Chaplot, Dhiraj Gandhi 项目地址&#xff1a;https://devendrachaplot.github.io/projects/Neural-SLAM 代码地址&#xff1a;https://github.com/devendrachaplot/N…

Java超级玛丽小游戏制作过程讲解 第一天 创建窗口

package com.sxt;import javax.swing.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener;public class MyFrame extends JFrame implements KeyListener {//设置窗口的大小为800*600public MyFrame() {this.setSize(800, 600);//设置窗口中显示this.setLo…

2023牛客暑期多校训练营6-A Tree

2023牛客暑期多校训练营6-A Tree https://ac.nowcoder.com/acm/contest/57360/A 文章目录 2023牛客暑期多校训练营6-A Tree题意解题思路代码 题意 解题思路 最大价值和这个数据范围&#xff0c;一眼 d p dp dp。 直接在树上并不好处理&#xff0c;问题是如何有效转化、处理…

Android Ble蓝牙App(二)连接与发现服务

Ble蓝牙App&#xff08;二&#xff09;连接与发现服务 前言正文一、GATT回调二、连接和断连三、连接状态回调四、发现服务五、服务适配器六、显示服务七、源码 前言 在上一篇中我们进行扫描设备的处理&#xff0c;本文中进行连接和发现服务的数据处理&#xff0c;运行效果图如下…

SystemVerilog scheduler

文章目录 简介调度器simulation regionPreponed regionActive regionInactive regionNBA(Non-blocking Assignment Events region)Observed regionReactive regionRe-Inactive Events regionRe-NBA RegionPostponed Region PLI region:Pre-active regionPre-NBA regionPost-NBA…

JMeter 4.x 简单使用

文章目录 前言JMeter 4.x 简单使用1. 启动2. 设置成中文3. 接口测试3.1. 设置线程组3.2. HTTP信息请求头管理器3.3. 添加HTTP请求默认值3.4. 添加HTTP cookie 管理3.5. 添加http请求3.5.1. 添加断言 3.6. 添加监听器-查看结果树3.7. 添加监听器-聚合报告 4. 测试 前言 如果您觉…

探索产品项目管理软件的种类及功能

随着科技的不断发展&#xff0c;越来越多的企业开始重视产品项目管理的重要性。产品项目管理软件作为一种有效的工具&#xff0c;可以帮助企业更好地规划、执行和控制项目&#xff0c;提高项目的成功率。本文将分为两部分&#xff0c;分别介绍产品项目管理软件的功能以及一些知…

java实现钉钉群机器人@机器人获取信息后,机器人回复(机器人接收消息)

1.需求 鉴于需要使用钉钉群机器人回复&#xff0c;人们提出的问题&#xff0c;需要识别提出的问题中的关键词&#xff0c;后端进行处理实现对应的业务逻辑 2.实现方式 用户群机器人&#xff0c;附带提出的问题&#xff0c;后端接收消息后识别消息内容&#xff0c;读取到关键…

深度学习,神经网络介绍

目录 1.神经网络的整体构架 2.神经网络架构细节 3.正则化与激活函数 4.神经网络过拟合解决方法 1.神经网络的整体构架 ConvNetJS demo: Classify toy 2D data 我们可以看看这个神经网络的网站&#xff0c;可以用来学习。 神经网络的整体构架如下1&#xff1a; 感知器&…

完全背包(从二维到一维)

图片来源活动 - AcWing 有 N件物品和一个容量为 V 的背包&#xff0c;每件物品有各自的价值且能被选择无数次&#xff0c;要求在有限的背包容量下&#xff0c;装入的物品总价值最大。 一&#xff0c;暴力解法&#xff08;容易超时&#xff09; #include<iostream> usi…

Java课题笔记~ 关联映射

一、MyBatis关联查询 在关系型数据库中&#xff0c;表与表之间存在着3种关联映射关系&#xff0c;分别为一对一、一对多、多对多。 一对一&#xff1a;一个数据表中的一条记录最多可以与另一个数据表中的一条记录相关。列如学生与学号就属于一对一关系。 一对多&#xff1a;主…