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

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


目录

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

1. 问题背景

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

复制代码
bash

coderboots
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. 核心代码

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

复制代码
python


coderboots
import requests
import logging
import time

class ArticleApiTest:
    def __init__(self):
        self.base_url = "http://localhost:8081/api/article"
        
        # 设置请求头,确保与浏览器一致(后面证明只需要修改代理即可)
        self.headers = {

        }
        
        # 设置Cookies
        self.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 response
        except requests.RequestException as e:
            self.logger.error(f"Request failed: {str(e)}")
            return None

def 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

代码:

复制代码
python


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

修改点 2:完整的 Headers 和 Cookies

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

代码:

复制代码
python


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

修改点 3:日志记录

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

代码:

复制代码
python


coderboots
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. 最终测试结果

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

复制代码
yaml


coderboots
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_url
        self.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 = 1
        response = 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 = 1
        response = 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()
相关推荐
火车叼位8 小时前
脚本伪装:让 Python 与 Node.js 像原生 Shell 命令一样运行
运维·javascript·python
孤狼warrior8 小时前
YOLO目标检测 一千字解析yolo最初的摸样 模型下载,数据集构建及模型训练代码
人工智能·python·深度学习·算法·yolo·目标检测·目标跟踪
Katecat996638 小时前
YOLO11分割算法实现甲状腺超声病灶自动检测与定位_DWR方法应用
python
玩大数据的龙威9 小时前
农经权二轮延包—各种地块示意图
python·arcgis
ZH15455891319 小时前
Flutter for OpenHarmony Python学习助手实战:数据库操作与管理的实现
python·学习·flutter
belldeep9 小时前
python:用 Flask 3 , mistune 2 和 mermaid.min.js 10.9 来实现 Markdown 中 mermaid 图表的渲染
javascript·python·flask
喵手9 小时前
Python爬虫实战:电商价格监控系统 - 从定时任务到历史趋势分析的完整实战(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·零基础python爬虫教学·电商价格监控系统·从定时任务到历史趋势分析·采集结果sqlite存储
喵手9 小时前
Python爬虫实战:京东/淘宝搜索多页爬虫实战 - 从反爬对抗到数据入库的完整工程化方案(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·零基础python爬虫教学·京东淘宝页面数据采集·反爬对抗到数据入库·采集结果csv导出
B站_计算机毕业设计之家10 小时前
猫眼电影数据可视化与智能分析平台 | Python Flask框架 Echarts 推荐算法 爬虫 大数据 毕业设计源码
python·机器学习·信息可视化·flask·毕业设计·echarts·推荐算法
PPPPPaPeR.10 小时前
光学算法实战:深度解析镜片厚度对前后表面折射/反射的影响(纯Python实现)
开发语言·python·数码相机·算法