大模型并不"认识"你的系统

很多人第一次使用 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 里(早期写的,字段名不一样)
api_client.post("/api/v2/orders", json={"productId": "p1", "qty": 1, ...})

# 测试文件 C 里(用了另一套封装)
order_service.create(product="p1", count=1)

复制代码

AI 做语义检索时,可能找到旧的、不规范的写法,导致生成的代码风格不一致,甚至用了已经废弃的字段名。

问题二:检索噪音增大

100 个文件里有大量相似的接口调用代码,AI 在检索时需要处理大量干扰项,可能反而找不到最相关的参考,生成质量下降。


解决方案:API 层 + Service 层

工程化的解法是将代码分成三层:

复制代码

tests/          ← 测试用例层(只关心测试逻辑)
  └── order/
      └── test_create_order.py

services/       ← 业务逻辑层(封装多个接口的串联调用)
  └── order_service.py

api/            ← 接口调用层(每个接口对应一个函数,一处定义)
  └── order_api.py

复制代码

api/order_api.py:接口调用层

每个接口只在这里定义一次,是整个工程的"接口字典":

复制代码

# api/order_api.py
"""
订单模块接口定义
所有订单相关接口的调用都从这里发出,禁止在测试文件中直接拼接接口路径。
"""
from utils.http_client import APIClient


def create_order(client: APIClient, product_id: str, quantity: int,
                 address_id: str, coupon_code: str = None, remark: str = None):
    """创建订单"""
    payload = {
        "product_id": product_id,
        "quantity": quantity,
        "address_id": address_id,
    }
    if coupon_code:
        payload["coupon_code"] = coupon_code
    if remark:
        payload["remark"] = remark
    return client.post("/api/v2/orders", json=payload)


def get_order(client: APIClient, order_id: str):
    """查询订单详情"""
    return client.get(f"/api/v2/orders/{order_id}")


def list_orders(client: APIClient, page: int = 1, page_size: int = 20, status: str = None):
    """查询订单列表"""
    params = {"page": page, "page_size": page_size}
    if status:
        params["status"] = status
    return client.get("/api/v2/orders", params=params)


def cancel_order(client: APIClient, order_id: str, reason: str):
    """取消订单"""
    return client.post(f"/api/v2/orders/{order_id}/cancel", json={"reason": reason})

复制代码

services/order_service.py:业务逻辑层

把需要多个接口串联的常见业务流程封装成公共方法:

复制代码

# services/order_service.py
"""
订单业务逻辑层
封装常用的多步骤业务流程,供测试用例直接调用。
"""
from api.order_api import create_order, get_order, cancel_order
from utils.http_client import APIClient


def create_and_get_order(client: APIClient, product_id: str, quantity: int,
                          address_id: str) -> dict:
    """
    创建订单并立即查询,返回完整订单信息。
    适用于需要验证创建后状态的测试场景。
    """
    create_resp = create_order(client, product_id, quantity, address_id)
    assert create_resp.status_code == 201, f"创建订单失败: {create_resp.text}"
    order_id = create_resp.json()["data"]["order_id"]

    get_resp = get_order(client, order_id)
    assert get_resp.status_code == 200
    return get_resp.json()["data"]


def create_pending_order(client: APIClient) -> str:
    """
    使用默认参数快速创建一个待支付订单,返回 order_id。
    适用于其他测试(如支付测试、取消测试)的前置条件。
    """
    resp = create_order(
        client,
        product_id="prod_test_001",
        quantity=1,
        address_id="addr_test_001"
    )
    assert resp.status_code == 201
    return resp.json()["data"]["order_id"]

复制代码

测试文件如何使用这两层

复制代码

# tests/order/test_create_order.py
from api.order_api import create_order
from services.order_service import create_and_get_order

class TestCreateOrder:
    def test_create_order_success(self, api_client):
        """正常创建订单"""
        order = create_and_get_order(api_client, "prod_001", 2, "addr_123")
        assert order["status"] == "pending"
        assert order["total_amount"] > 0

    def test_create_order_missing_product_id(self, api_client):
        """缺少必填字段 product_id"""
        resp = create_order(api_client, product_id="", quantity=1, address_id="addr_123")
        assert resp.status_code == 400
        assert resp.json()["message"] == "product_id 不能为空"

复制代码


分层架构对 AI 的好处

有了 API 层 + Service 层之后,AI 做语义检索的效果会大幅提升:

没有分层有分层
AI 在 100 个测试文件里搜索"如何调用创建订单接口"AI 直接检索到 api/order_api.py,一处即知
找到多种写法,不知道用哪个接口层唯一,写法统一
多步骤流程散落在各个测试文件里Service 层集中封装,直接复用
新测试参考旧测试,风格越来越乱新测试参考 API 层和 Service 层,风格一致

升级后的工程目录结构:

复制代码

api-autotest/
├── api/                    ← 接口调用层(每个接口定义一次)
│   ├── order_api.py
│   ├── user_api.py
│   └── product_api.py
├── services/               ← 业务逻辑层(多接口串联的公共流程)
│   ├── order_service.py
│   └── user_service.py
├── tests/                  ← 测试用例层(只关心测试逻辑)
│   ├── order/
│   ├── user/
│   └── product/
├── utils/
├── fixtures/
├── config/
├── conftest.py
└── pytest.ini

复制代码


Rules 文件:让 AI 遵守你的工程规范

为什么需要 Rules 文件

有了分层架构之后,还有一个问题:AI 不知道你定了这些规范。

下次你让 AI 写测试用例时,它可能还是会在测试文件里直接写 api_client.post("/api/v2/orders", ...),而不是调用你封装好的 create_order() 函数。

解决方法是使用 Cursor Rules 文件——这是 Cursor 的一个核心功能,让你可以把工程规范直接"写给 AI 看",让它在每次生成代码时都遵守这些规则。


Rules 文件是什么

Rules 文件本质上是附加在每次 AI 对话中的系统提示词(System Prompt)。你在 Rules 文件里写的内容,会在每次 AI 生成代码前被自动注入,让 AI 理解你的项目规范。

Cursor 支持两种 Rules:

类型存放位置作用范围
Project Rules.cursor/rules/*.mdc只对当前项目生效
User RulesCursor Settings → Rules对所有项目全局生效

推荐方案:工程规范放 Project Rules,个人偏好(比如"回复用中文")放 User Rules。


如何创建 Rules 文件

方法一:通过 Cursor 界面创建(推荐新手)
  1. 打开 Cursor,进入你的项目
  2. 按 Cmd+Shift+P(macOS)/ Ctrl+Shift+P(Windows)打开命令面板
  3. 输入 New Cursor Rule,回车
  4. 输入规则名称(比如 api-test-rules),回车
  5. Cursor 会自动在 .cursor/rules/ 目录下创建 api-test-rules.mdc 文件
方法二:手动创建
mkdir -p .cursor/rules
touch .cursor/rules/api-test-rules.mdc

然后用 Cursor 打开这个文件,开始编写规则内容。


4.4 Rules 文件的格式

.mdc 文件支持 Markdown 格式,开头有一段 YAML Front Matter 用于配置规则的触发时机:

复制代码

---
description: 接口自动化工程编码规范
globs:        # 匹配哪些文件时触发此规则
  - "tests/**/*.py"
  - "api/**/*.py"
  - "services/**/*.py"
alwaysApply: false   # 是否对所有文件始终生效
---

复制代码

globs 的作用:当 AI 正在操作匹配这些路径的文件时,自动附加此规则。比如你正在写测试文件,Rules 会自动生效,不需要你手动提醒 AI。

alwaysApply: true:如果你希望所有操作都遵守这条规则(比如"始终用中文回复"),可以设置为 true。


4.5 为接口测试工程编写 Rules 文件

下面是一个完整的示例,可以直接用于你的接口测试工程:

复制代码

---
description: 接口自动化工程编码规范
globs:
  - "tests/**/*.py"
  - "api/**/*.py"
  - "services/**/*.py"
alwaysApply: false
---

# 接口自动化工程编码规范

## 工程结构

本工程采用三层架构,职责如下:
- `api/`:接口调用层,每个接口有且只有一处定义,命名规范为 `{模块名}_api.py`
- `services/`:业务逻辑层,封装需要多接口串联的公共业务流程
- `tests/`:测试用例层,只关注测试逻辑,不直接拼接接口路径

## 编写测试用例的强制规范

### 1. 禁止在测试文件中直接调用 HTTP 客户端

**错误示范**(禁止):

def test_create_order(api_client):
    api_client.post("/api/v2/orders", json={...})  # ❌ 禁止


**正确示范**:

from api.order_api import create_order
from services.order_service import create_pending_order

def test_create_order(api_client):
    resp = create_order(api_client, ...)  # ✅ 使用 api 层


### 2. 优先使用 Service 层的公共方法

当一个操作需要多步接口调用时,优先检查 `services/` 目录下是否已有封装好的方法。
例如需要"创建订单后查询"时,使用 `order_service.create_and_get_order()`,
而不是手动写两次接口调用。

### 3. 新增接口时必须先在 api 层定义

如果需要调用一个 `api/` 目录下还没有的接口,必须先在对应的 `{模块}_api.py` 文件中定义该接口函数,然后再在测试文件中引用。

### 4. 测试用例命名规范

- 文件名:`test_{被测功能}.py`(如 `test_create_order.py`)
- 类名:`Test{功能名驼峰}` (如 `TestCreateOrder`)
- 方法名:`test_{场景描述}`(如 `test_create_order_missing_product_id`)

### 5. 断言规范

- 必须断言 HTTP 状态码
- 必须断言响应体中的核心业务字段
- 错误场景必须断言错误信息的具体内容(`message` 字段)

## 语言规范

- 所有代码注释使用中文
- docstring 必须说明:函数功能、适用测试场景

复制代码


4.6 Rules 文件生效后的效果

有了这个 Rules 文件,当你告诉 AI:

帮我写一个支付订单的测试用例,接口是 POST /api/v2/orders/{order_id}/pay,
需要先有一个待支付的订单

AI 会自动:

  1. 检查 api/order_api.py 是否已有 pay_order() 函数,没有的话先补充
  2. 检查 services/order_service.py 是否有 create_pending_order() 可复用,有的话直接用
  3. 生成符合命名规范的测试类和方法名
  4. 断言状态码 + 业务字段

复制代码

# AI 按照 Rules 规范自动生成:

# 1. 先补充 api 层(如果没有)
# api/order_api.py
def pay_order(client: APIClient, order_id: str, payment_method: str):
    """支付订单"""
    return client.post(f"/api/v2/orders/{order_id}/pay",
                       json={"payment_method": payment_method})

# 2. 测试用例(复用了 Service 层的 create_pending_order)
# tests/order/test_pay_order.py
from api.order_api import pay_order
from services.order_service import create_pending_order

class TestPayOrder:
    def test_pay_order_success(self, api_client):
        """正常支付:使用微信支付成功场景"""
        order_id = create_pending_order(api_client)  # 复用 Service 层
        resp = pay_order(api_client, order_id, "wechat")
        assert resp.status_code == 200
        assert resp.json()["data"]["status"] == "paid"

    def test_pay_order_already_paid(self, api_client):
        """异常:重复支付已完成的订单"""
        order_id = create_pending_order(api_client)
        pay_order(api_client, order_id, "wechat")   # 第一次支付
        resp = pay_order(api_client, order_id, "wechat")  # 第二次支付
        assert resp.status_code == 409
        assert resp.json()["message"] == "订单已支付"

复制代码

完全符合你定义的规范,不需要你再手动检查和纠正。


4.7 Rules 文件的进阶技巧

技巧一:为不同目录创建不同 Rules

.cursor/rules/ 目录下可以有多个 .mdc 文件,每个针对不同场景:

.cursor/rules/
├── api-test-rules.mdc       # 接口测试规范(作用于 tests/ api/ services/)
├── api-layer-rules.mdc      # API 层开发规范(作用于 api/)
└── general-rules.mdc        # 通用规范(alwaysApply: true)

技巧二:在 Rules 中引用文件

可以在 Rules 中指定"参考这个文件的风格":

## 代码风格参考

当生成新的接口函数时,参考 `api/order_api.py` 的代码风格。
当生成新的测试类时,参考 `tests/order/test_create_order.py` 的结构。

技巧三:把常见错误场景也写进 Rules

## 常见错误与修正

- **不要使用 time.sleep()**,如需等待,使用 pytest 的 `poll` 机制或重试装饰器
- **不要硬编码 token**,必须从环境变量读取
- **不要在测试中创建真实的外部资源**(如发短信、发邮件),使用 mock

5. 完整实践流程总结

把本篇所有内容串起来,形成一套完整的工作流:

复制代码

┌─────────────────────────────────┐
│     Step 1:喂知识给 AI          │
│  API 文档 OR F12 抓包 + 功能描述  │
└──────────────┬──────────────────┘
               │
┌──────────────▼──────────────────┐
│     Step 2:写第一个测试用例      │
│  AI 生成 → 你校正 → 确认无误      │
└──────────────┬──────────────────┘
               │
┌──────────────▼──────────────────┐
│     Step 3:利用语义检索扩展      │
│  存量代码成为参考,增量知识即可    │
└──────────────┬──────────────────┘
               │ 代码多了,语义噪音↑
┌──────────────▼──────────────────┐
│  Step 4:抽象 API 层 + Service 层 │
│  接口一处定义,公共流程集中封装    │
└──────────────┬──────────────────┘
               │
┌──────────────▼──────────────────┐
│     Step 5:编写 Rules 文件       │
│  把工程规范"写给 AI 看",强制遵守  │
└──────────────┬──────────────────┘
               │
┌──────────────▼──────────────────┐
│     持续扩展:只需录入增量知识     │
│  新接口 → 定义到 api 层 → 写测试   │
└─────────────────────────────────┘

复制代码

阶段你做什么AI 做什么
喂知识提供接口信息或抓包数据理解接口,推断边界场景
写第一个用例审查并纠正 AI 的推断生成完整测试代码
扩展阶段只说"帮我写 XXX 的测试"语义检索参考存量代码,自主生成
工程治理维护 api 层、service 层、rules 文件严格遵守规范,风格统一
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐