当前位置: 首页 > article >正文

基于 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()
   


http://www.kler.cn/a/473434.html

相关文章:

  • WebSocket监听接口
  • 【C++】B2106 矩阵转置
  • 晨辉面试抽签和评分管理系统之一:考生信息管理和编排
  • 多模态大模型初探索:通过ollama部署多模态大模型
  • maven如何从外部导包
  • 数仓建模:如何判断一个数仓模型的好坏?
  • 【ROS2】从零开始使用URDF构建机器人
  • java之Collection
  • USB 驱动开发 --- Gadget 设备连接 Windows 免驱
  • 基于物联网疫苗冷链物流监测系统设计
  • go语言学习 笔记 1(变量,语法,数据类型)
  • 【.NET】Kafka消息队列介绍,使用Confluent.Kafka集成Kafka消息队列
  • 如何使用脚手架工具开始,快速搭建一个 Express 项目的基础架构
  • Online Judge PTA 最大公约数与最小公倍数
  • 网络安全 基础入门-概念名词
  • 文件读写到SQLite数据库的方法
  • C++编程等级认证学习计划day2-1
  • 万界星空科技质量管理QMS系统具体功能介绍
  • AT6668-6N-22:BDS定位SOC芯片,常用在车载系统
  • TensorRT-LLM中的MoE并行推理
  • 【linux系统之redis6】redisTemplate的使用方法
  • 如何轻松反转C# List<T>中的元素顺序
  • “多维像素”多模态雷视融合技术构建自动驾驶超级感知能力|上海昱感微电子创始人蒋宏GADS演讲预告
  • Kafka优势剖析-消费者组、并行消费
  • JavaFX基础之环境配置,架构,FXML
  • GoChina备案管家