基于 Python 自动化接口测试(踩坑与实践)

文档:基于 Python 的自动化接口测试


在这里插入图片描述

目录

  1. 背景
  2. 问题描述与解决思路
  3. 核心代码
  4. 修改点及其详细解释
  5. 最终测试结果
  6. 后续优化建议

1. 问题背景

本项目旨在使用 Python 模拟浏览器的请求行为,测试文章分页接口的可用性。测试目标接口如下:

bashcoderboots
http://localhost:8081/api/article/page

接口需要携带与浏览器完全一致的请求头和 Cookies,同时需支持分页参数(如 currentsize)。

重点是, 使用postman和浏览器都可以正常测试,但是使用python脚本测试失败。 —遇到网络问题, 一定要记得思考是否是代理问题。


2. 问题描述与解决思路

问题描述

  1. 初次尝试时,脚本请求失败,返回 502 Bad Gateway 错误。
  2. 原因分析表明,requests 库默认继承系统代理配置,而代理拦截或错误转发了请求。
  3. 此外,初始代码未完全复制浏览器的 Headers 和 Cookies。

解决思路

  1. 禁用代理:显式设置 proxiesNone,避免系统代理干扰。
  2. 完整复制 Headers 和 Cookies:确保请求与浏览器的行为一致。
  3. 日志改进:详细记录请求 URL、Headers 和响应信息,便于调试和问题定位。
  4. 重试机制:为网络不稳定的情况添加重试逻辑,提高脚本健壮性。

3. 核心代码

以下是经过优化的测试脚本:

pythoncoderboots
import requests
import logging
import timeclass ArticleApiTest:def __init__(self):self.base_url = "http://localhost:8081/api/article"# 设置请求头,确保与浏览器一致(后面证明只需要修改代理即可)self.headers = {}# 设置Cookiesself.cookies = {}# 创建 session 并禁用代理self.session = requests.Session()self.session.headers.update(self.headers)self.session.cookies.update(self.cookies)self.session.proxies = {'http': None, 'https': None}# 设置超时时间self.timeout = 10# 设置日志记录logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')self.logger = logging.getLogger(__name__)def get_page(self, current=1, size=10):"""发送分页请求"""url = f"{self.base_url}/page"params = {'current': current, 'size': size}try:# 发送请求response = self.session.get(url, params=params, timeout=self.timeout, verify=False)# 记录日志self.logger.info(f"Request URL: {response.url}")self.logger.info(f"Response Status: {response.status_code}")if response.status_code == 200:self.logger.info("Request successful")self.logger.info(f"Response Data: {response.json()}")else:self.logger.error(f"Request failed with status code: {response.status_code}")return responseexcept requests.RequestException as e:self.logger.error(f"Request failed: {str(e)}")return Nonedef main():tester = ArticleApiTest()print("开始测试...")response = tester.get_page()if response and response.status_code == 200:print("✅ 测试成功")else:print("❌ 测试失败")if __name__ == "__main__":main()

4. 修改点及详细解释

修改点 1:禁用代理 --重点和关键

  • 原因:初次运行时,系统代理干扰了请求,导致 502 Bad Gateway 错误。
  • 解决方法:在 requests.Session 中添加 proxies 参数,将 httphttps 显式设置为 None

代码:

pythoncoderboots
self.session.proxies = {'http': None, 'https': None}

修改点 2:完整的 Headers 和 Cookies

  • 原因:部分请求头(如 User-Agentsec-ch-ua)以及 Cookies 在初始代码中未设置,导致服务器未正确识别请求。(由于本次后端其实没有做特别的鉴权,所以这里其实设置为空也可以正常访问)
  • 解决方法:复制浏览器中的完整 Headers 和 Cookies 并在 requests.Session 中更新。

代码:

pythoncoderboots
self.headers = {# 浏览器请求头
}
self.cookies = {# 浏览器 Cookies
}

修改点 3:日志记录

  • 原因:初始代码缺乏详细的日志,不利于调试。
  • 解决方法:添加请求 URL、Headers 和响应状态的详细日志记录。

代码:

pythoncoderboots
self.logger.info(f"Request URL: {response.url}")
self.logger.info(f"Response Status: {response.status_code}")
self.logger.info(f"Response Data: {response.json()}")

5. 最终测试结果

运行脚本后,成功返回分页数据,日志记录如下:

yamlcoderboots
2025-01-08 01:42:21,175 - INFO - Request URL: http://localhost:8081/api/article/page?current=1&size=10
2025-01-08 01:42:21,175 - INFO - Response Status: 200
2025-01-08 01:42:21,176 - INFO - Request successful
2025-01-08 01:42:21,176 - INFO - Response Data: {...}
✅ 测试成功

6. 后续优化建议(略)

  1. 动态 CSRF Token 支持
    • 如果接口需要动态 Token,可以在发送请求前自动提取并添加到 Headers。
  2. 重试机制
    • 针对请求失败的情况(如网络不稳定或服务器错误),增加智能重试机制。
  3. 异步请求
    • 如果需要测试多个接口,可以使用 asyncio 实现异步请求,提高效率。
  4. 自动化集成
    • 将脚本集成到 CI/CD 管道中,定期验证接口的可用性。

通过上述改进,该脚本现已具备稳定性、可调试性和一致性,能够准确模拟浏览器请求行为并测试目标接口。

最后给一个好用的模版:

修改template 为你的模块名称即可

import requests
import json
from colorama import init, Fore, Style
import os# 初始化colorama
init()# 禁用系统代理
os.environ['no_proxy'] = '*'class TemplateApiTest:def __init__(self, base_url="http://localhost:8081/api"):self.base_url = base_urlself.headers = {"Content-Type": "application/json"}def print_response(self, api_name, response):"""格式化打印响应结果"""print(f"\n{Fore.CYAN}测试接口:{Style.RESET_ALL} {api_name}")print(f"{Fore.CYAN}请求URL:{Style.RESET_ALL} {response.url}")print(f"{Fore.CYAN}状态码:{Style.RESET_ALL} {response.status_code}")if response.status_code == 200:print(f"{Fore.GREEN}响应结果:{Style.RESET_ALL}")try:formatted_json = json.dumps(response.json(), ensure_ascii=False, indent=2)print(formatted_json)except:print(response.text)else:print(f"{Fore.RED}错误响应:{Style.RESET_ALL}")print(response.text)print("-" * 80)def test_get_page(self):"""测试分页查询模板"""params = {"current": 1,"size": 10,"category": "通用模板"}response = requests.get(f"{self.base_url}/template/page",params=params,headers=self.headers)self.print_response("分页查询模板", response)def test_get_template_by_id(self):"""测试根据ID获取模板"""template_id = 1response = requests.get(f"{self.base_url}/template/{template_id}",headers=self.headers)self.print_response(f"获取模板(ID: {template_id})", response)def test_save_template(self):"""测试保存新模板"""template_data = {"name": "测试模板","content": "这是一个测试模板的内容","category": "通用模板","description": "用于测试的模板"}response = requests.post(f"{self.base_url}/template",headers=self.headers,data=json.dumps(template_data))self.print_response("创建新模板", response)def test_update_template(self):"""测试更新模板"""template_data = {"id": 1,"name": "更新后的测试模板","content": "这是更新后的测试模板内容","category": "通用模板","description": "已更新的测试模板"}response = requests.put(f"{self.base_url}/template",headers=self.headers,data=json.dumps(template_data))self.print_response("更新模板", response)def test_delete_template(self):"""测试删除模板"""template_id = 1response = requests.delete(f"{self.base_url}/template/{template_id}",headers=self.headers)self.print_response(f"删除模板(ID: {template_id})", response)def main():# 创建测试实例tester = TemplateApiTest()try:print(f"\n{Fore.YELLOW}=== 开始测试模板接口 ==={Style.RESET_ALL}")tester.test_get_page()tester.test_get_template_by_id()tester.test_save_template()tester.test_update_template()tester.test_delete_template()print(f"{Fore.YELLOW}=== 模板接口测试完成 ==={Style.RESET_ALL}\n")except requests.exceptions.RequestException as e:print(f"{Fore.RED}测试过程中发生错误: {e}{Style.RESET_ALL}")if __name__ == "__main__":main()

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

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

相关文章

k8s dashboard离线部署步骤

确定k8s版本,以1.23为例。 部署metrics-server服务,最好用v0.5.2。 用v0.6.0,可能会报以下错误: nodekubemaster:~/Desktop/metric$ kubectl top nodes Error from server (ServiceUnavailable): the server is currently unabl…

python学opencv|读取图像(二十八)使用cv2.warpAffine()函数平移图像

【1】引言 前序已经对图像操作进行了广泛的学习,包括读取、放大缩小,改变BGR通道值等,相关链接包括且不限于: python学opencv|读取图像-CSDN博客 python学opencv|读取图像(三)放大和缩小图像_python(1)使…

【LeetCode】力扣刷题热题100道(11-15题)附源码 环形链表 二叉树中序遍历 插入法(C++)

目录 1.字母异位词分组 2.环形链表 3.环形链表2 4.二叉树的中序遍历 5.搜索插入位置 1.字母异位词分组 给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 排序字符…

Java一个简单的反弹动画练习

文章目录 说明代码详解创建窗体代码创建绘图板创建线程 运行结果完整代码 说明 做了一个小球和星型做反弹动画的窗体作为练习,分享给大家,为了方便和我一样的小白可以看的比较明白,所以尽量详细的标注了注释,希望能帮到同样在学习…

监控观测数据标签体系的应用实践

前言 在复杂的应用系统环境下,监控数据量呈现出海量且繁杂的特点,如何高效地对这些监控数据进行管理、分析以及从中挖掘出有价值的信息,成为保障系统稳定运行和优化性能的关键所在。数据标签体系的建立就变得十分重要,它能够为监…

Vue中el-tree结合vuedraggable实现跨组件元素拖拽

实现效果&#xff1a; 左侧el-tree: <template><el-treeclass"filter-tree":data"treeData":props"defaultProps":filter-node-method"filterNode"node-key"id"draggable:allow-drop"allowDrop"node-dr…

PHP民宿酒店预订系统小程序源码

&#x1f3e1;民宿酒店预订系统 基于ThinkPHPuniappuView框架精心构建的多门店民宿酒店预订管理系统&#xff0c;能够迅速为您搭建起专属的、功能全面且操作便捷的民宿酒店预订小程序。 该系统不仅涵盖了预订、退房、WIFI连接、用户反馈、周边信息展示等核心功能&#xff0c;更…

点击底部的 tabBar 属于 wx.switchTab 跳转方式,目标页面的 onLoad 不会触发(除非是第一次加载)

文章目录 1. tabBar 的跳转方式2. tabBar 跳转的特点3. 你的配置分析4. 生命周期触发情况5. 总结 很多人不明白什么是第一次加载&#xff0c;两种情况讨论&#xff0c;第一种情况假设我是开发者&#xff0c;第一次加载就是指点击微信开发者工具上边的编译按钮&#xff0c;每点击…

三维卷积( 3D CNN)

三维卷积&#xff08; 3D CNN&#xff09; 1.什么是三维卷积 1.1 三维卷积简介 二维卷积是在单通道的一帧图像上进行滑窗操作&#xff0c;输入是高度H宽度W的二维矩阵。 三维卷积输入多了深度C这个维度&#xff0c;输入是高度H宽度W深度C的三维矩阵。在卷积神经网络中&…

电脑硬盘系统迁移及问题处理

一、系统迁移准备 1、确认你的电脑主板是否支持安装两块硬盘,如电脑主板有多个M2硬盘接口,我们将新硬盘安装到主板上,原来的老硬盘安装在第二个接口上,主板只有一个M2接口的话可以使用移动硬盘盒。 2、新硬盘安装好后,我们进入原来的系统,在 此电脑–右键–管理–磁盘管…

游戏语音的历史是什么样的?

游戏中&#xff0c;离不开游戏社交。 无社交&#xff0c;不游戏&#xff0c;大家都深知社交在游戏体验中的重要性。 游戏语音的发展史是怎么样的&#xff1f;问了下AI&#xff0c;给我的回答是 早期阶段 1970年代&#xff1a;1970年代出现了第一个语音游戏“尤瓦尔的冒险”&am…

GDPU Android移动应用 重点习题集

目录 程序填空 ppt摘选 题目摘选 “就这两页ppt&#xff0c;你还背不了吗” “。。。” 打开ppt后 “Sorry咯&#xff0c;还真背不了&#x1f61c;” 更新日志 考后的更新日志 没想到重点勾了一堆&#xff0c;还愣是没考到其中的内容&#xff0c;翻了一下&#xff0c;原…

排序:插入、选择、交换、归并排序

排序 &#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性 &#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序&#xff0c;…

计算机网络 (34)可靠传输的工作原理

前言 计算机网络可靠传输的工作原理主要依赖于一系列协议和机制&#xff0c;以确保数据在传输过程中能够准确无误地到达目的地。 一、基本概念 可靠传输指的是数据链路层的发送端发送什么&#xff0c;在接收端就收到什么&#xff0c;即保证数据的完整性、正确性和顺序性。由于网…

C++:string

一、string概念 之前介绍过通过字符数组保存字符串&#xff0c;然后对字符数组中的字符串做各种操作&#xff1b;为了更加简单方便&#xff0c;在C中&#xff0c;又增加了 string 来处理字符串。 char str[20] "hello world"; string 字符串其实是一种更加高级的封…

SQL Server 数据库给第三方用户开权限,限制可见内容

单独数据库权限的设置&#xff1a; 方法&#xff1a; 给外方公司开用户&#xff0c;让其访问本地有限资源。 分两步&#xff0c;1新建服务器登录名&#xff0c;2设置数据库用户权限 1&#xff0c;首先用管理员sa登录数据库&#xff0c;在服务器级别下“安全性\登录名”&#…

Opus Clip AI技术浅析(二):上传与预处理

1. 视频上传 1.1 用户接口 用户通过网页或移动应用上传视频文件。文件上传通常使用HTTP协议&#xff0c;支持多种视频格式&#xff08;如MP4, AVI, MOV等&#xff09;。上传接口需要处理大文件上传、断点续传等问题。 1.2 文件传输 上传的视频文件通过安全的传输协议&#…

二叉树层序遍历 Leetcode102.二叉树的层序遍历

二叉树的层序遍历相当于图论的广度优先搜索&#xff0c;用队列来实现 &#xff08;二叉树的递归遍历相当于图论的深度优先搜索&#xff09; 102.二叉树的层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右…

Linux第一课:c语言 学习记录day06

四、数组 冒泡排序 两两比较&#xff0c;第 j 个和 j1 个比较 int a[5] {5, 4, 3, 2, 1}; 第一轮&#xff1a;i 0 n&#xff1a;n个数&#xff0c;比较 n-1-i 次 4 5 3 2 1 // 第一次比较 j 0 4 3 5 2 1 // 第二次比较 j 1 4 3 2 5 1 // 第三次比较 j 2 4 3 2 1 5 // …

保护性暂停原理

什么是保护性暂停&#xff1f; 保护性暂停&#xff08;Guarded Suspension&#xff09;是一种常见的线程同步设计模式&#xff0c;常用于解决 生产者-消费者问题 或其他需要等待条件满足后再继续执行的场景。通过这种模式&#xff0c;一个线程在执行过程中会检查某个条件是否满…