基于Pytest+Requests+Allure实现接口自动化测试

一、整体结构
框架组成:pytest+requests+allure

设计模式:

关键字驱动

项目结构:

工具层:api_keyword/

参数层:params/

用例层:case/

数据驱动:data_driver/

数据层:data/

逻辑层:logic/

二、具体步骤及代码
1、工具层

将get、post等常用行为进行二次封装。

代码(api_key.py)如下:

import allure
import json
import jsonpath
import requests# 定义一个关键字类
class ApiKey:# 将get请求行为进行封装@allure.step("发送get请求")def get(self, url, params=None, **kwargs):return requests.get(url=url, params=params, **kwargs)# 将post请求行为进行封装@allure.step("发送post请求")def post(self, url, data=None, **kwargs):return requests.post(url=url, data=data, **kwargs)# 由于接口之间可能相互关联,因此下一个接口需要上一个接口的某个返回值,此处采用jsonpath对上一个接口返回的值进行定位并取值@allure.step("获取返回结果字典值")def get_text(self, data, key):# json数据转换为字典json_data = json.loads(data)# jsonpath取值value = jsonpath.jsonpath(json_data, '$..{0}'.format(key))return value[0]

其中引用allure.step()装饰器进行步骤详细描述,使测试报告更加详细。

使用jsonpath对接口的返回值进行取值。

2、数据层

数据采用yaml文件。

代码(user.yaml)如下:

-user:username: adminpassword: '123456'msg: successtitle: 输入正确账号、密码,登录成功
-user:username: admin1password: '1234561'msg: 用户名或密码错误title: 输入错误账号1、密码1,登录失败
-user:username: admin2password: '1234562'msg: 用户名或密码错误title: 输入错误账号2、密码2,登录失败

其中title是为了在用例进行时动态获取参数生成标题。

3、数据驱动层

对数据进行读写。

代码(yaml.driver.py)如下:

import yamldef load_yaml(path):file = open(path, 'r', encoding='utf-8')data = yaml.load(file, Loader=yaml.FullLoader)return data

4、参数层

参数层存放公共使用的参数,在使用时对其进行调用。

代码(allParams.py)如下:

'''规则:全局变量使用大写字母表示
'''# 地址
URL = 'http://39.98.138.157:'# 端口
PORT = '5000'

5、逻辑层

用例一:进行登录的接口请求,此处登录请求在yaml文件里设置了三组不同的数据进行请求。

用例二:进行个人查询的接口请求,此处需要用到登录接口返回的token值。

用例三、进行添加商品到购物车的接口请求,此处需要用到登录接口返回的token值以及个人查询接口返回的openid、userid值

用例四、进行下单的接口请求,此处需要用到登录接口返回的token值以及个人查询接口返回的openid、userid、cartid值

注意:由于多数接口需要用到登录接口返回的token值,因此封装一个conftest.py定义项目级前置fixture,在整个项目只执行一次,可以在各个用例中进行调用(其他共用参数也可以采取类似前置定义)。同时由于此处定义的项目级fixture,因此可以将初始化工具类ak = ApiKey()也放入其中。

代码(conftest.py)如下:
 

from random import randomimport allure
import pytestfrom pytest_demo_2.api_keyword.api_key import ApiKey
from pytest_demo_2.params.allParams import *def pytest_collection_modifyitems(items):"""测试用例收集完成时,将收集到的item的name和nodeid的中文显示在控制台上"""for item in items:item.name = item.name.encode("utf-8").decode("unicode_escape")item._nodeid = item.nodeid.encode("utf-8").decode("unicode_escape")# 项目级fix,整个项目只初始化一次
@pytest.fixture(scope='session')
def token_fix():# 初始化工具类ak = ApiKey()with allure.step("发送登录接口请求,并获取token,整个项目只生成一次"):# 请求接口# url = 'http://39.98.138.157:5000/api/login'url = URL + PORT + '/api/login'# 请求参数userInfo = {'username': 'admin','password': '123456'}# post请求res = ak.post(url=url, json=userInfo)# 获取tokentoken = ak.get_text(res.text, 'token')# 验证代码,验证token只生成一次token_random = random()return ak, token, res, token_random

其中也包含了防止中文乱码,加入了pytest_collection_modifyitems(函数)。

设置好conftest后,就可以应用在逻辑层里面了。

代码(shopingApi.py)如下:

import pytest
import allure
from pytest_demo_2.api_keyword.api_key import ApiKey
from pytest_demo_2.params.allParams import *class ApiCase():# 登录逻辑def params_login(self, userdata):# 动态获取参数生成标题allure.dynamic.title(userdata['title'])# 初始化工具类ak = ApiKey()# 请求接口url = URL + PORT + '/api/login'# 请求参数userInfo = {'username': userdata['user']['username'],'password': userdata['user']['password']}res = ak.post(url=url, json=userInfo)with allure.step("接口返回信息校验及打印"):print("/api/login登录接口请求响应信息")print(res.text)# 获取响应结果msg = ak.get_text(res.text, 'msg')print(msg)# 断言assert msg == userdata['msg']def params_getuserinfo(self, token_fix):# 从fix中获取预置的工具类和token,所有返回值都需要接收ak, token, res, token_random01 = token_fixwith allure.step("发送个人查询接口请求"):url = URL + PORT + '/api/getuserinfo'headers = {'token': token}res1 = ak.get(url=url, headers=headers)with allure.step("接口返回信息校验及打印"):print("/api/getuserinfo个人用户查询接口请求响应信息")print(res1.text)# print("验证的random值,测试用")# print(token_random01)name = ak.get_text(res1.text, 'nikename')# 断言assert "风清扬" == namereturn res1def params_addcart(self, token_fix):# 从fix中获取预置的工具类和token# 所有返回都要获取,不然会报错ak, token, res, token_random01 = token_fixwith allure.step("调用getuserinfo接口获取返回信息"):res1 = self.params_getuserinfo(token_fix)with allure.step("发送添加商品到购物车请求"):# 添加商品到购物车,基于token、userid、openid、productidurl = URL + PORT + '/api/addcart'hd = {"token": token}data = {"userid": ak.get_text(res1.text, 'userid'),"openid": ak.get_text(res1.text, 'openid'),"productid": 8888}# 发送请求res2 = ak.post(url=url, headers=hd, json=data)with allure.step("接口返回信息校验及打印"):print("/api/addcart添加商品到购物车请求响应信息")print(res2.text)# print("验证的random值,测试用")# print(token_random01)result = ak.get_text(res2.text, 'result')assert 'success' == resultreturn res2def params_createorder(self, token_fix):ak, token, res, token_random01 = token_fixwith allure.step("调用addcart接口获取返回信息"):res1 = self.params_addcart(token_fix)with allure.step("发送下单请求"):url = URL + PORT + '/api/createorder'# 从项目级fix中获取tokenhd = {"token": token}# 从添加商品到购物车接口中获取userid,openid,cartiddata = {"userid": ak.get_text(res1.text, 'userid'),"openid": ak.get_text(res1.text, 'openid'),"productid": 8888,"cartid": ak.get_text(res1.text, 'cartid')}res2 = ak.post(url=url, headers=hd, json=data)with allure.step("接口返回信息校验及打印"):print("/api/createorder下单请求响应信息")print(res2.text)# print("验证的random值,测试用")# print(token_random01)result = ak.get_text(res1.text, 'result')assert 'success' == result

6、用例层

调用逻辑层进行用例管理和数据传输。

代码(test_Tree.py)如下:

import allure
import pytest
from pytest_demo_2.data_driver import yaml_driver
from pytest_demo_2.logic.shopingApi import ApiCase@allure.epic("shopXo电商平台接口-接口测试")
class TestTree():# 初始化用例库actions1 = ApiCase()@allure.feature("01.登陆")@allure.story("02.一般场景")@pytest.mark.parametrize('userdata', yaml_driver.load_yaml('./data/user.yaml'))def test_case01(self, userdata):self.actions1.params_login(userdata)@allure.feature("02.个人查询")@allure.story("01.典型场景")@allure.title("个人查询")def test_case02(self, token_fix):self.actions1.params_getuserinfo(token_fix)@allure.feature("03.添加商品到购物车")@allure.story("01.典型场景")@allure.title("添加商品到购物车")def test_case03(self, token_fix):self.actions1.params_addcart(token_fix)@allure.feature("04.下单")@allure.story("01.典型场景")@allure.title("下单")def test_case04(self, token_fix):self.actions1.params_createorder(token_fix)

7、运行

代码(main_run.py)如下:

import os
import pytestdef run():pytest.main(['-v', './case/test_Tree.py','--alluredir', './result', '--clean-alluredir'])os.system('allure serve result')# os.system('allure generate ./result/ -o ./report_allure/ --clean')if __name__ == '__main__':run()

8、结果

最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走!

 

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

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

相关文章

玩转大数据19:数据治理与元数据管理策略

随着大数据时代的到来,数据已经成为企业的重要资产。然而,如何有效地管理和利用这些数据,成为了一个亟待解决的问题。数据治理和元数据管理是解决这个问题的关键。 1.数据治理的概念和重要性 数据治理是指对数据进行全面、系统、规范的管理…

MLOps在极狐GitLab 的现状和前瞻

什么是 MLOps 首先我们可以这么定义机器学习(Machine Learning):通过一组工具和算法,从给定数据集中提取信息以进行具有一定程度不确定性的预测,借助于这些预测增强用户体验或推动内部决策。 同一般的软件研发流程比…

行为型设计模式(一)模版方法模式 迭代器模式

模板方法模式 Template 1、什么是模版方法模式 模版方法模式定义了一个算法的骨架,它将其中一些步骤的实现推迟到子类里面,使得子类可以在不改变算法结构的情况下重新定义算法中的某些步骤。 2、为什么使用模版方法模式 封装不变部分:模版…

vscode配置node.js调试环境

node.js基于VSCode的开发环境的搭建非常简单。 说明:本文的前置条件是已安装好node.js(具体安装不再赘述,如有需要可评论区留言)。 阅读本文可掌握: 方便地进行js单步调试;方便地查看内置的对象或属性; 安装插件 C…

RouterSrv-DHCP

2023年全国网络系统管理赛项真题 模块B-Windows解析 题目 安装和配置DHCP relay服务,为办公区域网络提供地址上网。DHCP服务器位于AppSrv服务器上。拆分DHCP服务器上的作用域,拆分的百分比为7:3。InsideCli优先从RouterSrv获取地址。配置步骤 安装和配置DHCP relay服务,为办…

AIGC:阿里开源大模型通义千问部署与实战

1 引言 通义千问-7B(Qwen-7B)是阿里云研发的通义千问大模型系列的70亿参数规模的模型。Qwen-7B是基于Transformer的大语言模型, 在超大规模的预训练数据上进行训练得到。预训练数据类型多样,覆盖广泛,包括大量网络文本、专业书籍…

云原生消息流系统 Apache Pulsar 在腾讯云的大规模生产实践

导语 由 InfoQ 主办的 Qcon 全球软件开发者大会北京站上周已精彩落幕,腾讯云中间件团队的冉小龙参与了《云原生机构设计与音视频技术应用》专题,带来了以《云原生消息流系统 Apache Pulsar 在腾讯云的大规模生产实践》为主题的精彩演讲,在本…

Linux shell编程学习笔记37:readarray命令和mapfile命令

目录 0 前言1 readarray命令的格式和功能 1.1 命令格式1.2 命令功能1.3 注意事项2 命令应用实例 2.1 从标准输入读取数据时不指定数组名,则数据会保存到MAPFILE数组中2.2 从标准输入读取数据并存储到指定的数组2.3 使用 -O 选项指定起始下标2.4 用-n指定有效行数…

21.Servlet 技术

JavaWeb应用的概念 在Sun的Java Servlet规范中,对Java Web应用作了这样定义:“Java Web应用由一组Servlet、HTML页、类、以及其它可以被绑定的资源构成。它可以在各种供应商提供的实现Servlet规范的 Servlet容器 中运行。” Java Web应用中可以包含如下…

人工智能的发展之路:时间节点、问题与解决办法的全景解析

导言 人工智能的发展历程充满了里程碑式的事件,从早期的概念到今天的广泛应用,每个时间节点都伴随着独特的挑战和创新。本文将详细描述每个关键时间节点的事件,探讨存在的问题、解决办法,以及不同阶段之间的联系。 1. 195…

重温经典struts1之自定义转换器及注册的两种方式(Servlet,PlugIn)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 Struts的ActionServlet接收用户在浏览器发送的请求,并将用户输入的数据,按照FormBean中定义的数据类型,赋值给FormBean中每个变量&a…

Databend 源码阅读: Meta-service 数据结构

作者:张炎泼(XP) Databend Labs 成员,Databend 分布式研发负责人 drmingdrmer (张炎泼) GitHub 引言 Databend 是一款开源的云原生数据库,采用 Rust 语言开发,专为云原生数据仓库的需求而设计。 面向云架…

利用prometheus+grafana进行Linux主机监控

文章目录 一.架构说明与资源准备二.部署prometheus1.上传软件包2.解压软件包并移动到指定位置3.修改配置文件4.编写启动脚本5.启动prometheus服务 三.部署node-exporter1.上传和解压软件包2.设置systemctl启动3.启动服务 四.部署grafana1.安装和启动grafana2.设置prometheus数据…

第二节TypeScript 基础语法

1、typescript程序由以下几个部分组成: 模块函数变量语句和表达式注释 2、开始第一个typescript程序 创建一个typescript程序,使之输出“hello typescript”: 代码: var message:string "hello typescript" cons…

美颜SDK技术对比,深入了解视频美颜SDK的工作机制

如何在实时视频中呈现更加自然、美丽的画面,而这正是美颜SDK技术发挥作用的领域之一。本文将对几种主流视频美颜SDK进行深入比较,以揭示它们的工作机制及各自的优劣之处。 随着科技的不断进步,美颜技术已经从简单的图片处理发展到了视频领域…

Flink系列之:背压下的检查点

Flink系列之:背压下的检查点 一、Checkpointing under backpressure二、缓冲区 Debloating三、非对齐 Checkpoints四、对齐 Checkpoint 的超时五、限制六、故障排除 一、Checkpointing under backpressure 通常情况下,对齐 Checkpoint 的时长主要受 Che…

【运维面试100问】(十一)淡淡I/O过程

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》:python零基础入门学习 《python运维脚本》: python运维脚本实践 《shell》:shell学习 《terraform》持续更新中:terraform_Aws学习零基础入门到最佳实战 《k8…

关于“Python”的核心知识点整理大全32

目录 12.6.4 调整飞船的速度 settings.py ship.py alien_invasion.py 12.6.5 限制飞船的活动范围 ship.py 12.6.6 重构 check_events() game_functions.py 12.7 简单回顾 12.7.1 alien_invasion.py 12.7.2 settings.py 12.7.3 game_functions.py 12.7.4 ship.py …

本地MinIO存储服务如何创建Buckets并实现公网访问上传文件

文章目录 前言1. 创建Buckets和Access Keys2. Linux 安装Cpolar3. 创建连接MinIO服务公网地址4. 远程调用MinIO服务小结5. 固定连接TCP公网地址6. 固定地址连接测试 前言 MinIO是一款高性能、分布式的对象存储系统,它可以100%的运行在标准硬件上,即X86等…

管理类联考——数学——真题篇——按题型分类——充分性判断题——蒙猜E

老老规矩,看目录,平均每年2E,跟2D一样,D是全对,E是全错,侧面也看出10道题,大概是3A/B,3C,2D,2E,其实还是蛮平均的。但E为1道的情况居多。 第20题…