AI+Swagger:一键生成500条pytest接口用例

87个接口,手工点测3天,AI跑完3小时------核心不是模型多强,是Swagger够干净

大家好,我是某互联网公司的测试架构师。

上个月,团队接了一个订单中台的回归测试。87个接口,前后端分离,Swagger文档写得整整齐齐。测试组长看了一眼排期,说了一句:"按老规矩,3天起步。"

他说的"老规矩",是用Postman手工点测。87个接口,每个接口测正常流、缺参、类型错、边界值、鉴权,一个接口平均6-8条用例,加起来500多条。一个人点一遍,3天是乐观估计。

我说:"你让我用AI跑一遍试试。"

3小时后,CI上跑了529条pytest用例,全量回归通过。MR冒烟测试只要20分钟。

测试组长看完报告问了一句:"你怎么做到的?"

一、先别碰AI------把Swagger弄干净

这是整个流程里最容易被跳过、也最重要的一步。

我一开始也想着直接把Swagger文件喂给大模型,让它生成用例。结果AI生成了一堆不存在的字段------它把orderStatus写成了order_state,把amount的枚举值猜成了字符串数组。

后来我发现,问题不在AI,在Swagger本身。

我们要求每个接口必须满足五个条件:

  • OpenAPI 3.0,别拿Swagger 2.0凑合

  • operationId唯一,后面用例ID靠它

  • 每个schema字段尽量有example

  • 必填字段、枚举、最大最小长度写清楚

  • 错误响应别只写个400,把业务错误码也列出来

校验命令放在pre-commit里:

复制代码
openapi-spec-validator openapi.yaml

这一步很枯燥,但省不掉。Swagger越像合同,后面生成的用例越像回事。

二、把接口抽成"用例原材料"

Swagger清洗干净了,下一步不是直接生成测试文件,而是先生成一份可人工审核的YAML。

我写了一个脚本,把OpenAPI里的operation拉平:

复制代码
# tools/extract_ops.py
import yaml

HTTP_METHODS = {"get", "post", "put", "patch", "delete"}

def extract_operations(spec):
    for path, methods in spec["paths"].items():
        for method, op in methods.items():
            if method notin HTTP_METHODS:
                continue
            yield {
                "id": op.get("operationId") orf"{method}_{path}".replace("/", "_"),
                "method": method.upper(),
                "path": path,
                "summary": op.get("summary", ""),
                "parameters": op.get("parameters", []),
                "requestBody": op.get("requestBody", {}),
                "responses": op.get("responses", {}),
            }

if __name__ == "__main__":
    with open("openapi.yaml", encoding="utf-8") as f:
        spec = yaml.safe_load(f)
    ops = list(extract_operations(spec))
    with open("cases/raw_ops.yaml", "w", encoding="utf-8") as f:
        yaml.safe_dump(ops, f, allow_unicode=True, sort_keys=False)
    print(f"抽到 {len(ops)} 个 operation")

87个接口,抽出来87条operation。但这只是原材料,不是用例。

三、让AI干它擅长的:想场景

接口测试最烦的不是发请求,是想"还要测什么"。正常流谁都会写,缺参、类型错、边界值、权限、幂等------这些才费脑子。

我把每个operation的JSON发给模型,要求只输出JSON,不要解释:

复制代码
你是一个接口测试专家。下面是一个OpenAPI operation的JSON。
请生成pytest参数化用例,输出JSON数组,每个元素包含:
{
"id": "唯一ID",
"name": "用例名",
"path_params": {},
"query_params": {},
"headers": {},
"body": {},
"expected_status": 200,
"expected_assertions": []
}
覆盖场景:正常流、缺参、类型错、边界值、权限异常。

实测效果 :87个operation,AI生成了529条用例。平均每个接口6条------正好覆盖正常流、缺参、类型错、边界值、鉴权和幂等。

但AI生成的用例不能直接用。我让同事花了两小时做了一轮审核,主要检查三件事:

第一,断言写得太弱。 AI生成的断言往往是assert response.status_code == 200,只校验状态码。我要求改成assert data["code"] == 0 and data["data"]["orderId"] is not None。

第二,依赖关系没处理。 比如"取消订单"用例需要先有一个已支付的订单。AI不知道这个依赖,生成的用例直接调取消接口,必然404。

第三,业务规则缺失。 比如"已发货订单不能取消"------这条规则只存在于产品经理的脑子里,Swagger里没有。AI不知道,生成的用例就没覆盖。

AI负责把场景"想全",人负责把断言"写对"。

四、用pytest动态执行

AI生成的JSON用例,不直接转成.py文件,而是用参数化的方式动态执行:

复制代码
import pytest
import yaml
import requests

with open("cases/ai_cases.yaml") as f:
    ALL_CASES = yaml.safe_load(f)

@pytest.mark.parametrize("case", ALL_CASES)
def test_api(case, base_url, auth_token):
    url = base_url + case["path"]
    headers = {"Authorization": f"Bearer {auth_token}"}
    resp = requests.request(
        method=case["method"],
        url=url,
        params=case.get("query_params"),
        json=case.get("body"),
        headers=headers,
    )
    assert resp.status_code == case["expected_status"], (
        f"用例 {case['id']} 状态码不匹配"
    )
    for assertion in case["expected_assertions"]:
        # 简化示例,实际用jsonpath或schema校验
        assert assertion["key"] in resp.json()

为什么用参数化而不是生成静态文件?

因为Swagger在变,AI生成的用例也在变。参数化让用例和代码解耦------Swagger更新了,重新跑一遍AI生成流程,用例自动更新,不用改一行测试代码。

五、效果:3天到3小时

最终数据:

指标 手工Postman AI+pytest
接口数 87 87
用例数 手工写500+ AI生成529条
全量回归 3天 3小时
MR冒烟 半天 20分钟
用例维护 手动改 Swagger更新后自动重生成
人工投入 3天/轮 2小时审核 + 全自动执行

最关键的变化不是"快了",是"可以持续跑" 。以前手工点测,一个月跑一次就不错了。现在CI上每天跑,每次MR自动触发。

有团队在支付平台API测试中做了类似的尝试:Agent基于Swagger生成1200+用例,**用例生成时间从3天缩短到2小时,效率提升97%**。跨境支付汇率计算场景,资深工程师要琢磨2天的边界组合,AI用15分钟生成了27种参数组合的用例集。

六、踩过的坑

坑一:Swagger不干净,AI就编。

我一开始直接拿Swagger 2.0的文档喂模型,AI生成了大量不存在的字段。Swagger必须是OpenAPI 3.0,operationId唯一,必填和枚举写清楚。

坑二:只让AI"生成",不让AI"想"。

如果你只说"生成测试用例",AI会给你一堆assert 200的弱断言。你必须明确要求它覆盖正常流、缺参、类型错、边界值、权限、幂等六类场景。

坑三:依赖关系没处理。

"取消订单"依赖"已支付订单","退款"依赖"已支付订单"。AI不知道这些依赖,你需要给它一个依赖链的上下文,或者用Skills把依赖处理拆成独立步骤。

坑四:生成完不审核直接用。

AI生成的529条用例里,有大概60-80条需要人工修正。断言写弱了、业务规则漏了、依赖没配。审核2小时,比从零写500条用例省下来的时间不是一星半点,但审核这一步不能省。

最后

AI+Swagger的核心,不是"让AI写用例",是"把Swagger变成可执行的测试契约"。

Swagger写清楚了接口的"是什么"------路径、参数、类型、响应。AI补上了"还要测什么"------缺参、边界、鉴权、幂等。pytest负责"怎么跑"------参数化、断言、报告。

你不需要再手写500条用例了。你只需要把Swagger弄干净,让AI补场景,让pytest去干重复劳动。

下次你面对一个几百个接口的项目,别打开Postman了。打开Swagger文件,跑一遍清洗脚本,把operation丢给AI,说一句:

"帮我生成pytest参数化用例,覆盖正常流、缺参、类型错、边界值、权限和幂等。"

3小时后,CI上会跑完500多条用例。

相关推荐
一直在努力的小宁1 小时前
【阅读笔记11】机器人操作的数据金字塔《Data Pyramid for Embodied Manipulation》
人工智能
光锥智能1 小时前
OpenAI、Meta、Manus同时下注,智能体 2.0 来了
人工智能
揽秀亭长1 小时前
视频转脚本技术拆解:语音识别与文本处理流程
人工智能·音视频·语音识别
跨境联盟1 小时前
科普|小区落地社区健康驿站,普通居民可以获得哪些服务?
大数据·人工智能·健康医疗·健康管理·精准营养
IT_陈寒1 小时前
Python的GIL锁让我把多线程代码全重写了!
前端·人工智能·后端
高升说1 小时前
户外强光下的深度相机:940nm 窄带与曝光策略
人工智能·数码相机
Zootopia6261 小时前
美国载人飞船Crew-13明晚发射!
人工智能·算法·机器学习·数学建模·无人机·创业创新·信息与通信
艾莉丝努力练剑1 小时前
【AI大模型接入SDK】ChatSDK 集成测试概述
jvm·c++·人工智能·学习·面试·集成测试·sdk
探客木木夕1 小时前
AI伦理体系核心价值观声明
大数据·人工智能·机器学习