接口自动化测试完整详解(Python+pytest+requests+Allure 企业落地版)

接口自动化测试完整详解(Python+pytest+requests+Allure 企业落地版)

整体核心:分层自动化框架思想 + 核心技术实现 + CI持续集成 + 项目管理规范

一、框架选型与标准目录结构

1. 主流技术栈选型(图中标准组合)

Python + pytest + requests + Allure

各组件职责拆分:

组件 作用
Python 开发语言,语法简洁,第三方库丰富
pytest 单元/自动化测试框架,支持用例管理、参数化、夹具、后置前置
requests HTTP请求库,发送GET/POST/PUT等接口请求
Allure 高颜值可视化测试报告,展示步骤、断言、日志、失败截图
yaml/csv/excel 测试数据文件,实现数据驱动DDT
logging 日志模块,记录完整请求/响应报文
pymysql 数据库连接库,实现落库校验、造数、清理数据

2. 标准分层目录结构(企业通用规范)

复制代码
api_auto_test/
├── common/            # 公共封装层(核心工具类)
│   ├── http_client.py # 统一请求封装(url、token、header、ssl)
│   ├── assert_util.py # 通用断言工具(多层json、数据库断言)
│   ├── log_util.py    # 日志封装,打印完整请求响应
│   ├── db_util.py     # 数据库操作封装(查询/新增/清理)
│   └── tools.py       # 工具函数:提取json、时间、随机数、加密签名
├── config/            # 环境配置文件
│   ├── env.yaml       # 多环境域名、账号、数据库地址、全局token
│   └── setting.py     # 全局变量:报告路径、日志等级、文件路径
├── data/              # 测试数据层(数据驱动文件)
│   ├── login_data.yaml # 登录接口多组测试数据
│   └── order.csv      # 订单批量参数化数据
├── testcases/         # 测试用例层(按业务模块拆分)
│   ├── test_login.py  # 登录模块用例(提取token实现关联)
│   ├── test_user.py   # 用户信息接口
│   └── test_order.py  # 订单业务链路(登录→创建→查询→取消)
├── reports/           # 报告输出目录
│   ├── log/           # 运行日志文件
│   ├── raw/           # allure原始结果
│   └── html/          # 最终allure可视化html报告
├── conftest.py        # pytest全局夹具(前置登录、全局token、环境清理)
└── run.py             # 项目启动入口,一键执行全部用例并生成报告

二、核心技术要点拆解(全考点覆盖)

1. 请求封装 common/http_client.py

统一封装HTTP请求,解决重复代码、统一处理公共逻辑:

  • URL自动拼接:读取config环境域名,不用每个用例写完整地址
  • Token全局自动携带:登录后存入全局变量,后续接口自动塞入Header
  • 接口签名统一处理:加密算法封装,所有请求自动加sign签名
  • SSL证书忽略:测试环境跳过证书校验
  • 统一日志打印:自动记录请求头、请求体、响应码、响应JSON
  • 统一异常捕获:超时、连接失败、500异常统一捕获记录日志

极简封装示例代码:

python 复制代码
import requests
from common.log_util import logger
from config.setting import BASE_URL

class HttpClient:
    token = ""  # 全局静态token

    @classmethod
    def send_request(cls, method, path, params=None, json=None, headers=None):
        # 1. 拼接完整url
        url = BASE_URL + path
        # 2. 统一公共请求头
        base_headers = {"Content-Type": "application/json"}
        if cls.token:
            base_headers["Authorization"] = f"Bearer {cls.token}"
        if headers:
            base_headers.update(headers)
        # 3. 打印请求日志
        logger.info(f"请求地址:{url}, 请求方法:{method}")
        logger.info(f"请求头:{base_headers}, 请求参数:{json}")
        # 4. 发送请求
        resp = requests.request(
            method=method,
            url=url,
            params=params,
            json=json,
            headers=base_headers,
            verify=False  # 关闭ssl校验
        )
        logger.info(f"响应码:{resp.status_code}, 响应内容:{resp.text}")
        return resp.json()

2. 接口关联(参数动态提取与传递)

实现思路:
  1. 登录用例执行完成,提取返回token存入全局静态变量(HttpClient.token)
  2. 后续所有业务接口自动携带token,无需每个用例重复传参
  3. 链路场景:创建订单返回orderId,存入夹具变量,查询/取消订单直接读取
代码示例(test_login.py)
python 复制代码
import pytest
from common.http_client import HttpClient
from common.assert_util import assert_code_success

def test_login():
    # 发送登录请求
    req_data = {"username": "test01", "password": "123456"}
    res = HttpClient.send_request("POST", "/login", json=req_data)
    # 断言登录成功
    assert_code_success(res)
    # 提取token,全局共享
    HttpClient.token = res["data"]["token"]
    # 提取用户ID,存入pytest全局夹具
    pytest.user_id = res["data"]["userId"]

3. 数据驱动 DDT:@pytest.mark.parametrize + yaml/csv

作用:一套接口批量执行多组正向/边界/异常参数,减少重复用例代码

方式1:YAML文件读取参数(推荐,可读性高)

data/login_data.yaml

yaml 复制代码
cases:
  - name: 正常账号登录
    username: test01
    pwd: 123456
    expect_code: 200
  - name: 密码错误
    username: test01
    pwd: 666666
    expect_code: 400

用例读取yaml批量执行:

python 复制代码
import yaml
import pytest
from common.http_client import HttpClient

# 读取yaml数据
with open("./data/login_data.yaml", "r", encoding="utf-8") as f:
    login_cases = yaml.safe_load(f)["cases"]

@pytest.mark.parametrize("case", login_cases)
def test_login_param(case):
    res = HttpClient.send_request("POST", "/login", json={"username":case["username"], "password":case["pwd"]})
    assert res["code"] == case["expect_code"]
方式2:CSV批量数据(大批量造数场景)

搭配pandas读取csv,实现上千条账号参数化执行。

4. 多层断言 + 数据库落库校验

(1)多层JSON通用断言 common/assert_util.py

支持校验顶层code、嵌套字段、数组长度、字段非空

python 复制代码
def assert_code_success(response):
    """校验业务码200"""
    assert response["code"] == 200, f"业务失败:{response['msg']}"

def assert_json_field(res, json_path, expect_val):
    """多层字段断言,如$.data.user.name"""
    import jsonpath
    val = jsonpath.jsonpath(res, json_path)[0]
    assert val == expect_val
(2)数据库落库校验(接口自动化核心强校验)

场景:调用创建订单接口后,查询MySQL订单表,校验订单号、金额、状态是否正确落库

python 复制代码
from common.db_util import DB

def test_create_order():
    # 1. 调用创建订单接口
    req = {"goodsId": 1001, "num": 2}
    res = HttpClient.send_request("POST", "/order/create", json=req)
    order_id = res["data"]["orderId"]
    # 2. 查询数据库订单
    sql = f"select order_id, amount, status from t_order where order_id='{order_id}'"
    db_data = DB.query_one(sql)
    # 3. 数据库断言
    assert db_data["status"] == 1  # 状态1=待支付
    assert db_data["amount"] == 199.00

5. 完整日志记录 log_util.py

日志要求:

  • 区分日志等级:INFO正常报文、ERROR失败堆栈
  • 完整打印请求URL、请求头、入参、响应码、返回JSON
  • 日志按日期分文件保存,Allure报告可嵌入日志详情
python 复制代码
import logging
from config.setting import LOG_PATH

def get_logger():
    logger = logging.getLogger("api_auto")
    logger.setLevel(logging.INFO)
    # 文件输出+控制台输出
    file_handler = logging.FileHandler(LOG_PATH, encoding="utf-8")
    console_handler = logging.StreamHandler()
    fmt = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
    file_handler.setFormatter(fmt)
    logger.addHandler(file_handler)
    logger.addHandler(console_handler)
    return logger

logger = get_logger()

三、持续集成 CI/CD(Jenkins + Allure)

1. 整体流程

代码提交Git → Jenkins自动拉取代码 → 安装Python依赖 → 执行pytest自动化用例 → 生成Allure原始结果 → 渲染HTML报告 → 归档报告 + 邮件推送测试结果

2. Jenkins Shell执行脚本

bash 复制代码
# 1. 安装依赖
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

# 2. 清空历史报告
rm -rf reports/raw reports/html

# 3. 执行pytest,生成allure原始数据
pytest testcases/ --alluredir=reports/raw -s

# 4. 渲染allure可视化报告
allure generate reports/raw -o reports/html --clean

# 5. 判断用例失败,让Jenkins构建失败
if [ $? -ne 0 ];then
    echo "自动化用例存在失败!"
    exit 1
fi

3. 配套配置

  1. Jenkins插件:Allure Report、Email Extension
  2. 构建后操作:
    • 归档reports/html报告
    • 发送邮件:附件html报告,区分成功/失败邮件模板
  3. 触发方式:
    • 代码提交触发(GitLab WebHook)
    • 定时构建:每日凌晨2点全量回归核心链路

四、用例管理规范

1. 自动化用例与手工用例关联

  1. 自动化用例只覆盖核心业务流程(登录、下单、支付、查询),不覆盖极端低频异常;
  2. 每个自动化用例添加注释,关联测试管理平台用例ID(如#TC001 正常下单流程);
  3. 迭代更新:需求变更同步修改自动化脚本,保证和手工用例同步。

2. 环境清理与造数策略

(1)前置造数(conftest夹具)

@pytest.fixture(scope="module", autouse=True)

模块执行前自动创建测试账号、测试商品数据,保证用例有数据可执行。

(2)后置数据清理
  • 模块执行完成,删除本次自动化生成的订单、用户脏数据;
  • 避免数据库持续堆积测试数据,导致接口查询越来越慢;
  • 生产隔离:自动化单独一套性能/测试库,禁止操作线上库。

3. 分层执行策略

  1. 冒烟用例:仅核心链路,代码提交快速执行(5分钟内)
  2. 全量回归:定时任务执行所有自动化用例(夜间执行)
  3. 模块分组:通过@pytest.mark.order标记,Jenkins可单独执行订单模块。

五、面试高频考点总结

  1. 为什么分层设计common/config/data/testcases?
    解耦、复用、易维护,修改环境地址只改yaml,修改请求逻辑只改http_client。
  2. pytest如何实现接口关联?
    全局静态变量、夹具fixture共享参数,登录提取token存入全局请求类,下游自动携带。
  3. 数据驱动实现方式?
    @pytest.mark.parametrize + yaml/csv,多组参数批量执行,减少重复代码。
  4. 自动化和手工测试区别?
    自动化擅长重复回归、核心链路;手工擅长复杂交互、UI、低频异常场景。
  5. CI集成流程?
    Git触发Jenkins→拉代码→安装依赖→pytest执行→生成Allure报告→邮件通知。