从 0 开始学习 AI 测试 - 从接口测试来教你如何用 AI 来生成自动化测试代码
大模型并不"认识"你的系统
很多人第一次使用 Cursor 生成接口测试时会困惑, 大模型怎么知道我的系统的接口张什么样子?如果我们强行让它写,它绝对会写出一个假的的测试用例。这是因为大模型没有你系统的任何知识。它只能根据通用经验"猜"出一个看起来合理的接口,但猜的结果和你真实的系统大概率对不上。
AI 要生成准确的测试代码,前提是你必须先把接口知识喂给它。
知识的最佳来源:API 文档
如果你的团队有完善的 API 文档(Swagger、Postman Collection、API Blueprint 等),直接把相关接口文档丢给 AI 就可以了。
在 Cursor 中,你就可以:
(Agent 模式) @docs/api/order-api.md ← 引用文档文件 根据以上接口文档,帮我编写创建订单接口的完整测试用例, 包含正常创建、缺少必填字段、金额为负数三个场景。
AI 拿到文档后,可以准确理解接口的路径、方法、入参、返回值,生成的代码会非常准确。
没有文档怎么办:用 F12 抓包
现实情况是,很多团队的 API 文档严重滞后于代码,甚至根本没有文档。这时候最直接的办法是用浏览器开发者工具(F12)抓包。
PS: 我就是这么干的。
操作步骤
第一步:打开浏览器,进入你要测试的功能页面,按F12打开开发者工具,切换到 Network 标签页。
第二步:执行你要测试的操作(比如点击"创建订单"按钮),观察 Network 面板捕获到的请求。
第三步:找到目标请求,右键 → Copy → Copy as cURL,或者手动记录以下信息:
接口路径: POST /api/v2/orders 请求头: Content-Type: application/json Authorization: Bearer <token> 请求体: { "product_id": "prod_001", "quantity": 2, "address_id": "addr_123", "coupon_code": "SAVE10", "remark": "请尽快发货" } 响应状态码: 201 响应体: { "code": 0, "message": "success", "data": { "order_id": "ord_20260613_001", "status": "pending", "total_amount": 198.00, "created_at": "2026-06-13T14:00:00Z" } }第四步:把抓到的信息 + 对功能的简单描述一起给 AI:
(Agent 模式) 我抓到了一个创建订单的接口,信息如下: 接口:POST /api/v2/orders 请求体: { "product_id": "prod_001", "quantity": 2, "address_id": "addr_123", "coupon_code": "SAVE10", "remark": "请尽快发货" } 响应(成功): { "code": 0, "data": { "order_id": "ord_20260613_001", "status": "pending", "total_amount": 198.00 } } 功能说明:用户选好商品后,提交订单。product_id 和 quantity 是必填的, address_id 是收货地址,coupon_code 是优惠券(可选),remark 是备注(可选)。 请根据以上信息,帮我编写完整的接口测试用例。AI 会"推理"你没说清楚的部分
你会发现,上面的描述并没有告诉 AI 每个字段的所有细节(比如 quantity 的取值范围、product_id 的格式约束)。但这没关系——大模型会根据你描述的业务功能,自主推理出合理的测试边界。
比如 AI 会自动推断:
quantity可能有最小值(不能为 0 或负数)coupon_code是可选字段,需要测试不传的情况product_id不存在时应该报错- 库存不足时应该有对应的错误响应
AI 生成的测试用例可能包含你没想到的边界场景,这正是它的价值所在。
当 AI 推理错了怎么办?
直接纠正它:
你刚才假设 quantity 最大值是 99,实际上我们的系统限制是 999, 而且当超过库存数量时才会报错,不是超过 999 就报错。请修正。
AI 会立刻根据你的纠正更新测试用例,并自动调整相关的边界测试场景。这个过程类似于"代码审查"——AI 写草稿,你来校正,效率远高于从零手写。 当然也可以从一开始就把完整的测试用例给 AI, 这样就不用 AI 自己瞎猜了, 事实上我们项目中基本都是这样的。 但如果我们刚刚开始接受项目, 还没有完善的测试用例的时候, 也可以让 AI 自己去探索, 然后我们来纠正的这样一个模式。
那么接下来问题就来了, 以后我们每写一个自动化测试用例,都需要这么麻烦的去抓每个接口的包么? 事实上我们之前抓过的接口是不用重新给大模型的,这就涉及到 AI 编程最重要的一个部分了, 就是语义检索。
语义检索:存量代码就是最好的参考
Cursor 的代码库索引机制
当你在 Cursor 中打开一个项目,Cursor 会在后台自动对整个代码库做 Embedding(向量化),并存入向量数据库。
这意味着:
- 你写的每一行代码,Cursor 都"读"过了
- 当你提出新的需求时,AI 会通过语义检索找到项目中最相关的代码作为参考
- 它不是简单的关键词匹配,而是理解代码的语义含义
你可以在 Cursor 右下角看到索引进度:Indexing codebase... (234/312 files),索引完成后所有文件都可以被语义检索到。
PS:版本不同,这段信息的位置可能会有所不同。
存量代码如何成为"活文档"
让我们看一个具体的例子。
假设你按照第之前教程的方法,已经写好了第一个测试用例:
# tests/order/test_create_order.py class TestCreateOrder: def test_create_order_success(self, api_client): response = api_client.post("/api/v2/orders", json={ "product_id": "prod_001", "quantity": 2, "address_id": "addr_123" }) assert response.status_code == 201 data = response.json()["data"] assert "order_id" in data assert data["status"] == "pending"现在你想写"查询订单详情"的测试用例,你只需要告诉 AI:
帮我编写一个查询订单的测试用例。 它的测试步骤: 1. 创建订单,获取订单ID 2. 查询订单, 检验XXXXXX。 PS: 如果查询订单之前没有写过相关用例, 这里也需要去抓查询订单的接口的包。
此时 AI 不需要你重新解释创建订单的接口,大模型通过语义检索已经找到了test_create_order.py,直接参考现有风格生成新用例:
# AI 自动生成,风格与现有代码完全一致 class TestGetOrder: def test_get_order_success(self, api_client): # 先创建一个订单,再查询它 create_resp = api_client.post("/api/v2/orders", json={ "product_id": "prod_001", "quantity": 2, "address_id": "addr_123" }) order_id = create_resp.json()["data"]["order_id"] response = api_client.get(f"/api/v2/orders/{order_id}") assert response.status_code == 200 data = response.json()["data"] assert data["order_id"] == order_id assert data["status"] == "pending" assert "items" in data关键点:甚至你可以只说"查询订单详情",AI 自己知道要先创建订单再查询(因为它从已有代码中理解了这个业务流程)。
当然这样的形式实在过于代码冗余了,我们需要更灵活的接口,以及让我们的知识更加的简单。 毕竟以后代码库里的 case 越来越多, 大模型的语义检索能力也会收到干扰,并且我们的测试用例也得分层,不能把所有东西都写在用例里, 需要把 API,业务逻辑等等单独分层。 那怎么办呢? 看下面的内容。
增量知识积累
这就是语义检索带来的核心价值:项目里的代码越多,AI 能参考的知识越多,生成的代码质量越高。
第1个接口测试 → AI 需要你提供完整接口信息 第5个接口测试 → AI 已经理解了你的项目结构和风格 第20个接口测试 → AI 直接参考存量代码,你只需说"仿照 XXX 写一个 YYY" 第50个接口测试 → AI 几乎不需要额外解释,自主完成
实践建议:
- 每次引入一个新模块时,先手动写(或精心指导 AI 写)一个"示范性"测试用例
- 这个示范用例会成为该模块所有后续测试的参考基准
- 后续只需要增量录入新的业务知识(新字段、新规则),存量的调用方式 AI 自己会找
当代码多起来:Service 层抽象
语义检索也会"迷路"
随着项目发展,测试代码会越来越多。假设你已经有了 100 个测试文件,每个文件里都有调用各种接口的代码。这时候会出现两个问题:
问题一:同一功能有多种实现方式
# 测试文件 A 里创建订单的方式 api_client.post("/api/v2/orders", json={"product_id": "p1", "quantity": 1, ...}) # 测试文件 B 里(早期写的,字段名不一样)