金融项目实战 05|Python实现接口自动化——登录接口
目录
一、代码实现自动化理论及流程
二、脚本实现的理论和准备工作
1、抽取功能转为自动化用例
2、搭建环境(测试工具)
3、搭建目录结构
三、登录接口脚本实现
1、代码编写
1️⃣api目录
2️⃣script目录
2、断言
3、参数化
1️⃣编写数据存储文件:json文件
2️⃣编写读取数据工具:read_json()
3️⃣参数化引用:parameterize
一、代码实现自动化理论及流程
🔴代码编写脚本和工具实现脚本区别是什么?
- 代码:
- 优点:代码灵活方便
- 缺点:学习成本高
- 工具:
- 优点:易上手
- 缺点:灵活度低,有局限性。
- 总结:
- 功能脚本:工具
- 自动化脚本:代码
🔴代码接口自动化怎么做的?
- 第一步:(概述)python+request+unittest;
- 第二步:(具体描述)封装、调用、数据驱动、日志、报告;
- 第三步:(举例)api\scripts\data\log\report\until\...;
二、脚本实现的理论和准备工作
使用代码编写自动化脚本的流程:
- 1、抽取功能用例转为自动化⽤例。
- 2、搭建环境(测试工具相关的)
- 3、搭建目录结构
- 4、编写脚本
- 5、执行脚本
- 6、配置持续集成
1、抽取功能转为自动化用例
去掉了有bug的用例、以及“请求后台投资响应失败(密码为空)”的用例(改用例需要借钱和投资双方私下协商密码)

2、搭建环境(测试工具)
①python、pycharm、requests、pymysql、parametrize
②jenkins、jdk
提示:由于编写的自动化脚本,而自动化脚本编写之前功能已测试完毕,所以不需要在单独搭建项目环境。
3、搭建目录结构


三、登录接口脚本实现
1、代码编写
1️⃣api目录
把需要测的接口放在该目录
url设置成私有变量,只能在该类内部调用。
此处这样做只是因为url实际上只会在该登陆注册模块内部使用,外面没必须用到,设置私有,外部调用方法的时候。看着干净
![]()
from config import HOSTclass ApiRegisterLogin:# 有几个接口就封装几个方法#初始化def __init__(self, session):# 获取session对象self.session = session# 图片url# 图片验证码urlself.__url_img_code = HOST + "/common/public/verifycode1/{}"# 短信验证码urlself.__url_phone_code = HOST + "/member/public/sendSms"# 注册Lr1self.__url_register = HOST + "/member/public/reg"# 登录urlself.__url_login = HOST + "/member/public/login"# 登录状态urlself.__url_login_status = HOST + "/member/public/islogin"# url# 1、获取图⽚验证码接⼝ 封装def api_img_code(self,random):return self.session.get(url=self.__url_img_code.format(random))# 2、获取短信验证码接⼝ 封装def api_phone_code(self,phone,imgVerifyCode):data = {"phone": phone,"imgVerifyCode": imgVerifyCode,"type": "reg"}return self.session.post(url=self.__url_phone_code,data=data)# 3、注册接⼝ 封装def api_register(self,phone,password,verifycode,phone_code):data = {"phone": phone,"password": password,"verifycode": verifycode,"phone_code": phone_code,"dy_server": "on","invite_phone": ""}return self.session.post(url=self.__url_register,data=data)# 4、登录接⼝ 封装def api_login(self,keywords,password):data = {"keywords": keywords,"password": password}return self.session.post(url=self.__url_login, data=data)# 5、查询登录状态接⼝ 封装def api_login_status(self):return self.session.post(url=self.__url_login_status)
2️⃣script目录
调用封装的接口,开展测试工作

![]()
下面测试用例的内容目前只是测试一下api文件中封装的接口能不能用,后面还要改。
import unittestimport requestsfrom api.api_register_login import ApiRegisterLoginclass TestRegisterLogin(unittest.TestCase):# 初始化def setUp(self) -> None:# 获取session对象self.session =requests.Session()# 获取ApiRegisterLogin实例self.reg = ApiRegisterLogin(self.session)# 结束def tearDown(self) -> None:# 关闭session对象self.session.close()#1、获取图片验证码接口 测试def test01_img_code(self):# 调用图片验证码接口r = self.reg.api_img_code(234)# 查看响应状态码print(r.status_code)#2、获取短信验证码接口 测试def test02_phone_code(self,phone=17612341111,imgVerifyCode=8888):# 1、调用获取图片验证码接口 -- 目的:让session对象记录cookie# 调用接口后session会自动记录cookieself.reg.api_img_code(234)# 2、调用短信验证码接口r = self.reg.api_phone_code(phone=phone,imgVerifyCode=imgVerifyCode)# 3、查看响应结果print(r.json())#3、注册接口 测试def test03_register(self,phone=17612341111,imgVerifyCode=8888,password="win56",phone_code=666666):# 1、图片验证码接口self.reg.api_img_code(234)# 2、短信验证码接口self.reg.api_phone_code(phone=phone, imgVerifyCode=imgVerifyCode)# 3、注册接口r = self.reg.api_register(phone=phone,password=password,verifycode=imgVerifyCode,phone_code=phone_code)# 4、查看结果print(r.json())#4、登录接口 测试def test04_login(self,keywords=17612341111,password="win56"):# 1、调用登录r = self.reg.api_login(keywords=keywords,password=password)# 2、查看结果print(r.json())#5、查询登录状态接口 测试def test05_login_status(self):# 调用登录擦口self.reg.api_login(keywords=17612341111, password="win56")# 调用查询登录状态接口r = self.reg.api_login_status()# 看结果print(r.json())
2、断言
说明:判断程序执⾏实际结果是否符合预期结果
示例:
实际需要将api_register_login.py中的每个测试用例都做异常处理,下面只是以查询登录接口中的异常捕获为例。
中的完整代码后续补充。
try:# 调⽤登录接⼝self.reg.api_login(keywords="13600001111", password="test123")# 调⽤查询登录状态接⼝r = self.reg.api_login_status()# 看结果self.assertIn(expect_text, r.text)
except Exception as e:# ⽇志print(e)# 抛异常raise # 提示:捕获异常的⽬的是为了将错误信息记录下来,捕获信息完成后,必须抛出异常
【提示】:捕获异常的目的是为了将错误信息记录下来,捕获信息完成后,必须抛出异常
3、参数化
步骤:
- 1、编写数据存储⽂件 json
- 2、编写读取⼯具⽅法 read_json()
- 3、使⽤参数化组件进⾏引⽤ parametrize
1️⃣编写数据存储文件:json文件
心得:
1、根据模块来新建json文件(1个模块1个json⽂件)
2、最外侧使用{},模块下几个接口,编写几个key,值为列表
3、列表值中,有几组数据,就写几个{}
4、每组数据{}中,组成格式:说明+参数+预期结果
![]()
{"img_code": [{"desc": "获取图片验证码成功(随机小数)","random": 0.123,"expect_code": 200},{"desc": "获取图片验证码成功(随机整数)","random": 123,"expect_code": 200},{"desc": "获取图片验证码失败(随机数为空)","random": "","expect_code": 404},{"desc": "获取图片验证码失败(随机数为字符串)","random": "123hello","expect_code": 400}],"phone_code": [{"desc": "获取短信验证码成功","phone": "13600001111","imgVerifyCode": 8888,"expect_text": "发送成功"},{"desc": "获取短信验证码成功","phone": "13600001111","imgVerifyCode": 8889,"expect_text": "验证码错误"}],"register": [{"desc": "注册成功(必填参数)","phone": 13600001111,"password": "test123","verifycode": 8888,"phone_code": 666666,"expect_text": "注册成功"},{"desc": "注册失败(图片验证码错误)","phone": 13600001112,"password": "test123","verifycode": 8889,"phone_code": 666666,"expect_text": "验证码错误"},{"desc": "注册失败(短信验证码错误)","phone": 13600001112,"password": "test123","verifycode": 8888,"phone_code": 666667,"expect_text": "验证码错误"},{"desc": "注册失败(手机号已存在)","phone": 13600001111,"password": "test123","verifycode": 8888,"phone_code": 666666,"expect_text": "已存在"}],"login": [{"desc": "登录成功","keywords": 13600001111,"password": "test123","expect_text": "登录成功"},{"desc": "登录失败(密码为空)","keywords": 13600001111,"password": "","expect_text": "不能为空"},{"desc": "登录失败(解锁)","keywords": 13600001111,"password": "error123","expect_text": "登录成功"}],"login_status": [{"desc": "查询登录状态(已登录)","status": "已登录","expect_text": "OK"},{"desc": "查询登录状态(已登录)","status": "未登录","expect_text": "未登"}]
}
2️⃣编写读取数据工具:read_json()
![]()
import json
import osfrom config import DIR_PATHdef read_json(filename,key):# 拼接读取文件的完整路径# os.sep是动态获取/ \filepath = DIR_PATH + os.sep + "data" + os.sep +filenamearr = []with open(filepath,"r",encoding="utf-8") as f:for data in json.load(f).get(key):arr.append(list(data.values())[1:])return arrif __name__ == '__main__':# 测试一下能不能读取到数据print(read_json("register_login.json","img_code")) # 读取的数据为:[[0.123, 200], [123, 200], ['', 404], ['123hello', 400]]
3️⃣参数化引用:parameterize
难点1:错误次数锁定

难点2: 查询登录状态,不同结果。

【注意】由于parameterized的自身bug,运行测试用例必须是点击到测试用例所在的类名右键运行。如果想单独运行某个接口用例,则把其他接口代码先注释掉。
import unittest
from time import sleepimport requestsfrom api.api_register_login import ApiRegisterLoginfrom parameterized import parameterizedfrom util import read_jsonclass TestRegisterLogin(unittest.TestCase):# 初始化def setUp(self) -> None:# 获取session对象self.session =requests.Session()# 获取ApiRegisterLogin实例self.reg = ApiRegisterLogin(self.session)# 结束def tearDown(self) -> None:# 关闭session对象self.session.close()#1、获取图片验证码接口 测试@parameterized.expand(read_json("register_login.json","img_code"))def test01_img_code(self,random,expect_code):try:# 调用图片验证码接口r = self.reg.api_img_code(random)# 查看响应状态码# print(r.status_code)self.assertEqual(expect_code,r.status_code)except Exception as err:# 日志print(err)# 抛异常raise#2、获取短信验证码接口 测试@parameterized.expand(read_json("register_login.json", "phone_code"))def test02_phone_code(self,phone,imgVerifyCode,expec_text):try:# 1、调用获取图片验证码接口 -- 目的:让session对象记录cookie# 调用接口后session会自动记录cookieself.reg.api_img_code(234)# 2、调用短信验证码接口r = self.reg.api_phone_code(phone=phone,imgVerifyCode=imgVerifyCode)# 3、查看响应结果# print(r.json())self.assertIn(expec_text,r.text) # 使用text提取结果是更方便,json还要根据键找值except Exception as err:# 日志print(err)# 抛异常raise#3、注册接口 测试@parameterized.expand(read_json("register_login.json", "register"))def test03_register(self,phone,password,imgVerifyCode,phone_code,expec_text):try:# 1、图片验证码接口self.reg.api_img_code(234)# 2、短信验证码接口self.reg.api_phone_code(phone=phone, imgVerifyCode=imgVerifyCode)# 3、注册接口r = self.reg.api_register(phone=phone,password=password,verifycode=imgVerifyCode,phone_code=phone_code)# 4、查看结果# print(r.json())self.assertIn(expec_text,r.text)except Exception as err:# 日志print(err)# 抛异常raise#4、登录接口 测试@parameterized.expand(read_json("register_login.json", "login"))def test04_login(self,keywords,password,expec_text):try:i = 0r = Noneif "error" in password:while i <3:r=self.reg.api_login(keywords,password)i+=1# 锁定断言print("账号密码输错3次,账号锁定:",r.text)self.assertIn("锁定",r.text)# 暂停60秒sleep(60)r = self.reg.api_login(keywords=17612341111, password="win56")self.assertIn(expec_text,r.text)else:# 1、调用登录r = self.reg.api_login(keywords,password)# 2、查看结果# print(r.json())self.assertIn(expec_text, r.text)except Exception as err:# 日志print(err)# 抛异常raise#5、查询登录状态接口 测试@parameterized.expand(read_json("register_login.json", "login_status"))def test05_login_status(self,status,expec_text):try:if status == "已登录":# 调用登录擦口self.reg.api_login(keywords=17612341111, password="win56")# 调用查询登录状态接口r = self.reg.api_login_status()# 看结果# print(r.json())self.assertIn(expec_text, r.text)except Exception as err:# 日志print(err)# 抛异常raise
【总结】目前为止已经写的文件,文件内容上面均给出了代码

相关文章:
金融项目实战 05|Python实现接口自动化——登录接口
目录 一、代码实现自动化理论及流程 二、脚本实现的理论和准备工作 1、抽取功能转为自动化用例 2、搭建环境(测试工具) 3、搭建目录结构 三、登录接口脚本实现 1、代码编写 1️⃣api目录 2️⃣script目录 2、断言 3、参数化 1️⃣编写数据存储文件:jso…...
《HTML在网络安全中的多面应用:从防范攻击到安全审查》
Html基础 Html简介 HTML(HyperText Markup Language,超文本标记语言)是用于描述网页内容和结构的标准语言。以下是对HTML的简要介绍: 基本概念 定义: HTML不是一种编程语言,而是一种标记语言。 它使用标…...
Linux网络 | 学习传输层网络协议之UDP(短篇)
前言: 本节内容正式迈入传输层网络协议的知识殿堂, 之前的文章, 我们都是在应用层进行翻来覆去。 比如http就是应用层协议, 只不过使用了tcp的系统调用。 从本节开始, 友友们将会学习传输层两大协议: UDP和…...
iOS - 内存屏障的使用场景
内存屏障的使用是为了解决以下几个关键问题: 1. CPU 乱序执行 // 没有内存屏障时,CPU 可能乱序执行 void example() {// 这两行代码可能被 CPU 重排序a 1; // 操作1flag true; // 操作2 }// 使用内存屏障确保顺序 void safeExample() {a 1;…...
MySQL 8.0 新特性详解与实用示例
MySQL 8.0 新特性详解与实用示例 1. 引言 MySQL 8.0 是 MySQL 版本系列中具有里程碑意义的更新版本,带来了大量新功能和优化,极大地提升了数据库的性能和可用性。本文将深入介绍 MySQL 8.0 的主要新特性及其应用场景,帮助你在项目中更高效地…...
【STM32-学习笔记-5-】ADC
文章目录 ADCADC函数Ⅰ、ADC_InitTypeDef结构体参数①、ADC_Mode②、ADC_DataAlign③、ADC_ExternalTrigConv④、ADC_ContinuousConvMode⑤、ADC_ScanConvMode⑥、ADC_NbrOfChannel Ⅱ、ADC配置示例1、单次转换,非扫描单次转换非扫描模式下,获取多通道的…...
TY1801 反激变换器PWM GaN功率开关
TY1801 是一款针对离线式反激变换器的多模式 PWM GaN 功率开关。TY1801 内置 GaN 功率管,它具备超宽 的 VCC 工作范围,非常适用于 PD 快充等要求宽输出电压的应用场合,系统不需要使用额外的绕组或外围降压电路,节省系统 BOM 成本。TY1801 支持 Burst&…...
Jenkins安装、插件下载及构建环境配置详解
Jenkins简介 1.1 简介 Jenkins 是一个基于Java开发的开源持续集成工具,它提供了一个开放且易用的软件平台,主要用于自动化构建、测试和部署软件项目,以实现持续集成(CI)和持续交付/部署(CD)。…...
ESP32,uart安装驱动uart_driver_install函数剖析,以及intr_alloc_flags 参数的意义
在 uart_driver_install 函数中,参数 RX_BUF_SIZE * 2 指定了接收缓冲区(RX buffer)的大小。这个参数对于 UART 驱动程序来说非常重要,因为它决定了可以存储多少接收到的数据,直到应用程序读取它们为止。下面是对该函数…...
Ubuntu把应用程序放到桌面
有时候我们下载的软件是一个文件夹,通常需要进入进入指定文件夹下去执行.sh 文件来启动,下面来个实例如何把idea放到桌面 打开文件目录/usr/share/applications/或者~/.local/share/applications/目录。第一个目录是全局的,所有用户都可以使…...
什么是端口映射
端口映射 端口映射(Port Mapping)是一种网络技术,用于将外部网络请求转发到内部网络的特定设备或服务。它通常用于以下场景: 外部访问内部服务:允许外部用户通过公网IP访问内网中的设备或服务。多设备共享IP…...
数据结构《MapSet哈希表》
文章目录 一、搜索树1.1 定义1.2 模拟实现搜索 二、Map2.1 定义2.2 Map.Entry2.3 TreeMap的使用2.4 Map的常用方法 三、Set3.1 定义3.2 TreeSet的使用3.3 Set的常用方法 四、哈希表4.1 哈希表的概念4.2 冲突4.2.1 冲突的概念4.2.2 冲突的避免1. 选择合适的哈希函数2. 负载因子调…...
【QT】QComboBox:activated信号和currentIndexChanged信号的区别
目录 1、activated1.1 原型1.2 触发机制1.3 使用场景1.4 连接信号和槽的方法1.4.1 方式一1.4.2 方式二 2、currentIndexChanged2.1 原型2.2 触发机制2.3 使用场景2.4 连接信号和槽的方法 1、activated 1.1 原型 [signal] void QComboBox::activated(int index) [signal] void…...
【Block总结】ELGCA模块,池化-转置(PT)注意力和深度卷积有效聚合局部和全局上下文信息
ELGCA结构 论文题目:ELGC-Net: Efficient Local-Global Context Aggregation for Remote Sensing Change Detection 论文链接:https://arxiv.org/pdf/2403.17909 官方github:https://github.com/techmn/elgcnet 高效局部-全局上下文聚合器&…...
MERN全栈脚手架(MongoDB、Express、React、Node)与Yeoman详解
MERN 全栈脚手架是一种用于快速构建基于 MongoDB、Express、React 和 Node.js 的全栈应用的框架或模板。它帮助开发者快速启动项目,减少了从零开始配置的时间。以下是关于 MERN 全栈脚手架的详细解析。 一、MERN 技术栈简介 MongoDB: 文档型数据库,用于…...
基于springboot+vue+微信小程序的宠物领养系统
基于springbootvue微信小程序的宠物领养系统 一、介绍 本项目利用SpringBoot、Vue和微信小程序技术,构建了一个宠物领养系统。 本系统的设计分为两个层面,分别为管理层面与用户层面,也就是管理者与用户,管理权限与用户权限是不…...
如何使用策略模式并让spring管理
1、策略模式公共接口类 BankFileStrategy public interface BankFileStrategy {String getBankFile(String bankType) throws Exception; } 2、策略模式业务实现类 Slf4j Component public class ConcreteStrategy implements BankFileStrategy {Overridepublic String ge…...
react中hooks之useRef 用法总结
1. 基本概念 useRef 是 React 的一个 Hook,返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数。这个对象在组件的整个生命周期内保持不变。 2. 主要用途和特性 2.1 获取 DOM 元素实例 function TextInputWithFocusButton() {const inpu…...
使用 Docker 部署 Java 项目(通俗易懂)
目录 1、下载与配置 Docker 1.1 docker下载(这里使用的是Ubuntu,Centos命令可能有不同) 1.2 配置 Docker 代理对象 2、打包当前 Java 项目 3、进行编写 DockerFile,并将对应文件传输到 Linux 中 3.1 编写 dockerfile 文件 …...
如何在Ubuntu上安装和配置Git
版本控制系统(VCS)是软件开发过程中不可或缺的工具之一,它帮助开发者跟踪代码变更、协作开发以及管理不同版本的项目。Git作为当前最流行的分布式版本控制系统,因其高效性和灵活性而广受青睐。本文将指导你如何在Ubuntu操作系统上…...
Python合并Excel文档
有若干个Excel文档,每个文档格式一致,及第一行为文件标题,第二行为表格表头(表头不完全一致)。现需要将他们合并。合并规则为:去掉每个文档的第一行,以第二行为表头,将每个文档的第三…...
ARM PMU性能监控单元原理与实践指南
1. ARM PMU性能监控单元概述性能监控单元(PMU)是现代ARM处理器中用于硬件级性能分析的核心组件。它通过一组可编程的硬件计数器,实现对处理器内部各种关键事件的精确测量。这些事件涵盖了从指令执行、缓存访问到内存子系统行为等处理器活动的…...
2026论文降AI怎么挑?亲测好用工具附免费降AI指南
“您的论文AIGC率为42%,超出学校30%的合格线,请修改后重新提交。”赶毕业论文的同学这段时间估计没少收到这样的提醒。2026年知网、万方、维普等主流平台的AI检测算法持续迭代,把AI生成内容改到符合学校要求,已经成了毕业生的刚需…...
ssm207基于SSM的视频播放系统的设计与实现+vue(文档+源码)_kaic
第五章 系统的实现5.1 用户功能模块的实现5.1.1系统主界面用户进入本系统可查看系统信息,系统主界面展示如图5.1所示。图5.1网站主界面5.1.2视频详情界面用户可选择视频查看视频详情信息,并可进行视频播放操作,视频详情界面展示如图5.2所示。…...
厨房空调技术白皮书:从风冷到水冷,制冷系统在厨房场景中的工程化演进
厨房空调是暖通行业近三年技术迭代最密集的细分品类。从最初的"凉霸"(本质是风扇),到风冷分体式,再到水冷一体式,每代技术都在解决上一代没有覆盖的用户痛点。本文以工程技术视角,梳理四代厨房制…...
Web渗透测试能力成长地图:从工具使用到漏洞认知跃迁
1. 这不是工具清单,而是一张Web渗透测试的“能力成长地图”你刚点开这篇文章,大概率正站在两个路口之间:一边是网上铺天盖地的“十大免费扫描器推荐”,点进去全是截图下载链接一句“一键扫漏洞”,结果装完跑两下&#…...
3步快速解密中兴光猫配置:ZET工具终极实战指南
3步快速解密中兴光猫配置:ZET工具终极实战指南 【免费下载链接】ZET-Optical-Network-Terminal-Decoder 项目地址: https://gitcode.com/gh_mirrors/ze/ZET-Optical-Network-Terminal-Decoder 中兴光猫配置解密工具是每个网络管理员必备的神器!Z…...
昇腾CANN elec-ops-simulation 实战:电力系统仿真——潮流计算与暂态稳定分析在 NPU 上的加速
电力系统仿真:500 节点电网的牛顿-拉夫逊潮流计算 → 解 10001000 稀疏雅可比矩阵(每迭代 1 次矩阵求逆)→ CPU 迭代 15 次 2.4s。实时调度要求 < 100ms → NPU 加速:雅可比矩阵求解用 Cube 单元做批量小矩阵 LU 分解 → 每迭…...
企业级Veo 2提示词治理框架(含合规校验/版本回溯/效果归因三模块)——仅限首批500名开发者开放》
更多请点击: https://intelliparadigm.com 第一章:Veo 2提示词治理框架的核心定位与演进逻辑 Veo 2提示词治理框架并非单纯的技术工具升级,而是面向AIGC生产环境规模化、合规化与可审计化需求的战略性基础设施重构。其核心定位在于将离散、经…...
在多模型聚合场景下利用Taotoken实现API调用的自动降级与容灾
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 在多模型聚合场景下利用Taotoken实现API调用的自动降级与容灾 对于依赖大模型API的生产系统而言,服务的连续性与稳定性…...
