requests接口自动化测试

一、Requests 库核心函数 (HTTP 请求)

用于发送各种类型的 HTTP 请求,是接口测试的基础。

1. 顶层请求函数

函数名 用途 常用参数说明
requests.get() 发送 GET 请求 url, params(查询参数字典), headers, cookies, timeout
requests.post() 发送 POST 请求 url, data(表单字典), json(JSON 字典), files(上传文件), headers
requests.put() 发送 PUT 请求 通常用于更新资源,参数同 post (json 最常用)
requests.delete() 发送 DELETE 请求 通常用于删除资源
requests.request() 通用请求方法 method='GET', url, ... (可动态指定任意 HTTP 方法)

💡 关键区别

  • params: 自动拼接到 URL 后 (?key=value),用于 GET。
  • data: 提交 application/x-www-form-urlencoded 格式,用于 POST 表单。
  • json: 提交 application/json 格式,自动序列化字典为 JSON 字符串并设置 Header,用于 POST/PUT JSON 数据。
  • files: 用于文件上传,需配合 open(..., 'rb') 使用。

2. Response 响应对象属性与方法

请求返回的对象(如 resp = requests.get(...)),包含以下核心成员:

成员 类型 说明与用法
resp.status_code int 获取 HTTP 状态码 (200, 404, 500 等)
resp.json() dict/list 最常用。将响应体解析为 JSON 格式 (Python 字典或列表)
resp.text str 获取响应的文本内容 (自动根据编码解码)
resp.content bytes 获取响应的字节流下载图片/文件/视频时必须用此属性
resp.headers dict 获取响应头信息 (如 Content-Type, Set-Cookie)
resp.cookies RequestsCookieJar 获取响应中的 Cookie 对象
resp.url str 获取最终请求的 URL (若发生重定向,此为跳转后的地址)
resp.encoding str 查看或手动设置响应编码 (如 resp.encoding = 'utf-8')

二、Session 会话管理 (保持登录状态)

场景 :当接口之间存在依赖(如:先登录获取 Token/Cookie,再调用业务接口),必须使用 Session 对象来自动维护状态。

1. 核心方法与用法 (基于图片内容)

(1) 创建 Session 对象
复制代码
import requests
session = requests.Session()
(2) 使用 Session 发送请求

与普通 requests 用法一致,但自动携带该 Session 中保存的 Cookie 和 Header。

复制代码
# 第一次请求:登录,Session 自动保存返回的 Cookie
res_login = session.post(url_login, json={"user": "admin", "pwd": "123"})

# 第二次请求:业务操作,自动带上登录时的 Cookie,无需手动传
res_business = session.get(url_business)
(3) 共享/更新请求头 (全局设置)

重要函数session.headers.update()

用于在 Session 级别统一设置 Header(如 Token),后续所有请求自动生效。

复制代码
# 提取 token
token = res_login.json().get("token")

# 全局更新 Header
session.headers.update({
    "Authorization": f"Bearer {token}",
    "User-Agent": "Custom User Agent",  # 自定义 UA
    "Content-Type": "application/json"
})
(4) 关闭 Session
复制代码
session.close()

三、PyMySQL 数据库操作 (数据准备与校验)

用于测试前的数据构造 (插入测试数据)和测试后的结果验证 (查询数据库落库情况)或环境清理

1. 连接数据库 (基于图片内容)

复制代码
import pymysql

conn = pymysql.connect(
    host="192.168.1.100",   # 数据库服务器地址
    user="root",            # 登录用户名
    password="123456",      # 密码
    database="test_db",     # 要连接的数据库名称
    port=3306,              # 端口号 (默认 3306)
    charset="utf8"          # 字符集 (建议 utf8 或 utf8mb4)
)

2. 获取游标与执行 SQL

复制代码
cursor = conn.cursor()  # 获取游标对象

# 执行单条 SQL
sql = "SELECT * FROM users WHERE id = 1"
cursor.execute(sql)

# 执行带参数的 SQL (防注入)
sql_insert = "INSERT INTO users (name, age) VALUES (%s, %s)"
cursor.execute(sql_insert, ("ZhangSan", 18))

3. 获取查询结果 (基于图片内容)

方法 说明 返回值示例
cursor.fetchone() 获取1 行数据 ('ZhangSan', 18) (元组) 或 None
cursor.fetchmany(size) 获取指定行数数据 (元组列表)
cursor.fetchall() 获取全部数据 (元组列表)

4. 事务控制 (增删改必做)

复制代码
conn.commit()   # ✅ 提交事务:执行 INSERT/UPDATE/DELETE 后必须调用,否则不生效
conn.rollback() # ❌ 回滚事务:发生异常时调用,撤销操作

5. 关闭资源

复制代码
cursor.close()
conn.close()

四、JSON Schema 校验 (响应结构验证)

用于严格校验接口返回的 JSON 数据结构、字段类型、必填项是否符合契约,比简单的 assert 更强大。

1. 安装

复制代码
pip install jsonschema

2. 定义 Schema 规则

复制代码
schema = {
    "type": "object",
    "required": ["code", "msg", "data"],  # 必填字段
    "properties": {
        "code": {"type": "integer"},      # code 必须是整数
        "msg": {"type": "string"},        # msg 必须是字符串
        "data": {
            "type": "object",
            "properties": {
                "id": {"type": "integer"},
                "name": {"type": "string"}
            }
        }
    }
}

3. 执行校验

复制代码
import jsonschema

try:
    # instance: 实际响应数据 (resp.json())
    # schema: 定义的规则
    jsonschema.validate(instance=response.json(), schema=schema)
    print("✅ 结构校验通过")
except jsonschema.exceptions.ValidationError as e:
    print(f"❌ 结构校验失败: {e.message}")

五、RPC 接口测试 (Dubbo & Telnet)

针对非 HTTP 协议(如 Dubbo)的接口测试方法。

1. Telnet 命令 (手动测试)

适用于支持 Telnet 协议的 Dubbo 服务端。

复制代码
# 1. 连接
telnet <IP> <Port>

# 2. 常用命令
ls                # 查看服务列表
ps                # 查看提供者和消费者详情
invoke com.example.UserService.getUserById(1)  # 调用方法 (直接写 Java 方法调用形式)

2. dubboclient 库 (Python 自动化)

安装pip install dubbo-client

核心函数

复制代码
from dubbo_client import Client

# 1. 初始化客户端 (直连提供者 IP:Port 或 注册中心)
client = Client(['192.168.1.100:20880'])

# 2. 调用远程方法 (invoke)
result = client.invoke(
    interface='com.example.UserService',  # 接口全限定名
    method='getUserById',                 # 方法名
    args=[1],                             # 参数列表
    version='1.0.0',                      # 版本号 (可选)
    group='dubbo'                         # 分组 (可选)
)

print(result) # 输出反序列化后的 Python 对象

六、Pytest 框架集成与数据驱动

1. 核心装饰器与断言

名称 类型 说明
@pytest.mark.parametrize() 装饰器 数据驱动核心。传入参数名和参数值列表,自动生成多条用例。
assert 关键字 断言。例:assert resp.status_code == 200
setup_method() 特殊方法 每个 test_ 方法执行前运行 (常用于登录获取 Token)。
teardown_method() 特殊方法 每个 test_ 方法执行后运行 (常用于清理数据)。
pytest.main() 函数 在脚本内部启动测试。例:pytest.main(["-s", "test_api.py"])

2. 数据驱动示例

复制代码
import pytest
import requests

@pytest.mark.parametrize("username, pwd, expect_code", [
    ("admin", "123456", 200),
    ("user", "wrong", 500),
    ("", "123456", 400)
])
def test_login(username, pwd, expect_code):
    url = "http://api.com/login"
    resp = requests.post(url, json={"username": username, "password": pwd})
    assert resp.status_code == expect_code

3. JSON 文件驱动 (进阶)

将测试数据写在 .json 文件中,通过工具函数读取并传给 parametrize

复制代码
# 读取 JSON 并转换为列表 
def load_data():
    import json
    with open("data.json", "r", encoding="utf-8") as f:
        data = json.load(f)
    return [(item['user'], item['pwd'], item['code']) for item in data]

@pytest.mark.parametrize("user,pwd,code", load_data())
def test_login_dynamic(user, pwd, code):
    # 测试逻辑...
    pass

七、辅助工具函数汇总

模块 函数 用途
random random.randint(a, b) 生成随机整数 (如随机手机号、合同号)
time time.time() 获取当前时间戳 (浮点数)
组合 str(int(time.time())) 生成基于时间的唯一字符串 ID
json json.load(f) / json.dump() 读取/写入 JSON 配置文件
os/sys os.getcwd() 获取当前工作目录 (用于构建文件绝对路径)
内置 open(file, 'rb'/'wb') 二进制读写文件 (上传/下载必备)

🚀 综合实战流程示例

复制代码
import requests
import pymysql
import pytest
import random
import time

# 1. 前置准备 (Setup)
class TestContract:
    def setup_method(self):
        # A. 数据库连接 (准备数据)
        self.conn = pymysql.connect(host="...", user="...", password="...", database="...", charset="utf8")
        self.cursor = self.conn.cursor()
        
        # B. 登录获取 Token (Session 保持)
        self.session = requests.Session()
        login_data = {"user": "admin", "pwd": "123456"}
        resp = self.session.post("http://api.com/login", json=login_data)
        token = resp.json().get("token")
        self.session.headers.update({"Authorization": f"Bearer {token}"})

    def test_upload_contract(self):
        # C. 构造动态数据
        contract_no = f"HT{random.randint(10000, 99999)}_{int(time.time())}"
        
        # D. 发送请求 (文件上传)
        files = {"file": ("contract.pdf", open("contract.pdf", "rb"), "application/pdf")}
        params = {"contractNo": contract_no}
        
        resp = self.session.post("http://api.com/upload", params=params, files=files)
        
        # E. 断言
        assert resp.status_code == 200
        assert resp.json().get("code") == 200
        
        # F. 数据库校验 (验证是否落库)
        sql = "SELECT count(*) FROM contracts WHERE no = %s"
        self.cursor.execute(sql, (contract_no,))
        count = self.cursor.fetchone()[0]
        assert count == 1, "数据未成功写入数据库"

    def teardown_method(self):
        # G. 清理资源
        self.conn.rollback() # 测试数据回滚,保持环境干净
        self.cursor.close()
        self.conn.close()
        self.session.close()

if __name__ == "__main__":
    pytest.main(["-s", __file__])
相关推荐
踏着七彩祥云的小丑6 小时前
pytest——Mark标记
开发语言·python·pytest
不爱吃炸鸡柳7 小时前
Python入门第一课:零基础认识Python + 环境搭建 + 基础语法精讲
开发语言·python
Dxy12393102167 小时前
Python基于BERT的上下文纠错详解
开发语言·python·bert
SiYuanFeng9 小时前
Colab复现 NanoChat:从 Tokenizer(CPU)、Base Train(CPU) 到 SFT(GPU) 的完整踩坑实录
python·colab
炸炸鱼.10 小时前
Python 操作 MySQL 数据库
android·数据库·python·adb
_深海凉_10 小时前
LeetCode热题100-颜色分类
python·算法·leetcode
AC赳赳老秦11 小时前
OpenClaw email技能:批量发送邮件、自动回复,高效处理工作邮件
运维·人工智能·python·django·自动化·deepseek·openclaw
zhaoshuzhaoshu11 小时前
Python 语法之数据结构详细解析
python
AI问答工程师11 小时前
Meta Muse Spark 的"思维压缩"到底是什么?我用 Python 复现了核心思路(附代码)
人工智能·python
zfan52012 小时前
python对Excel数据处理(1)
python·excel·pandas