AI自动化接口测试:DeepSeek+Postman智能生成测试脚本实践
1. 项目概述:当Postman遇上DeepSeek,接口测试的“降维打击”
如果你和我一样,常年泡在接口测试的“苦海”里,一定对这样的场景不陌生:面对一个新项目,几十上百个接口文档摆在你面前,你需要手动在Postman里一个个创建请求,然后绞尽脑汁地设计测试用例,特别是那些复杂的断言逻辑——验证响应状态码、检查关键字段是否存在、判断数据类型、甚至验证嵌套JSON对象里的某个值是否符合预期。这个过程枯燥、重复,还容易出错。更头疼的是,当接口文档更新时,你的测试集合可能又要推倒重来。
这就是为什么当我开始尝试将DeepSeek这类大语言模型(LLM)与Postman结合时,感觉像是给手里的“瑞士军刀”装上了“智能导航”。这不仅仅是效率的提升,更像是一种工作范式的转变。简单来说,这个组合的核心价值在于: 让AI理解你的接口文档(无论是Swagger/OpenAPI、Markdown还是简单的文字描述),然后自动为你生成结构化的Postman集合,包括完整的请求参数、认证信息,以及最关键、最耗时的部分——智能、健壮的断言脚本。
它解决的痛点非常明确: 将测试工程师从大量重复、机械的配置工作中解放出来,让他们能更专注于测试策略设计、边界条件探索和业务逻辑验证这些更具创造性和挑战性的工作。 无论是前端、后端还是测试工程师,只要你的工作涉及API调试与验证,这套组合都能让你事半功倍。接下来,我就结合自己近期的实践,拆解一下如何实现这场“效率革命”。
2. 核心思路与工具选型背后的考量
2.1 为什么是Postman + DeepSeek?
在接口测试领域,工具选择很多,比如JMeter、Apifox、SoapUI等。我选择Postman作为落地点,主要基于几个现实考量:
Postman的普适性与生态成熟度: 它几乎是API开发者的“标配”。其直观的图形界面降低了使用门槛,强大的集合(Collection)、环境变量(Environment)、预请求脚本(Pre-request Script)和测试脚本(Tests)功能,构成了一个完整的测试工作流。更重要的是,Postman支持导出/导入集合(JSON格式),这为程序化生成和修改测试用例提供了可能。
DeepSeek的代码与逻辑理解能力: 在众多LLM中,我选择DeepSeek进行探索,是因为它在代码生成、逻辑推理和长文本理解方面表现突出。生成Postman测试脚本(本质上是JavaScript)正是其擅长领域。它不仅能根据接口描述生成基础断言,还能理解“业务逻辑”。例如,你告诉它“登录成功后返回的token需要用于后续请求的鉴权”,它能帮你生成在Tests脚本中提取token并存入环境变量的代码。
组合的化学反应: Postman提供了标准化的“容器”和运行环境,DeepSeek则扮演了“超级助手”,负责填充这个容器里最耗费脑力的内容(用例与断言)。两者的结合,实现了“标准化流程”与“智能化内容生成”的完美互补。
2.2 整体工作流设计
我设计的自动化流程,核心是构建一个“AI中间件”。这个中间件的工作流可以概括为以下几步:
- 输入处理: 接收各种格式的接口文档(Swagger JSON/YAML、Markdown、甚至自然语言描述)。
- AI解析与增强: 利用DeepSeek的API,将文档内容、你的测试意图(如“需要测试成功和失败场景”、“重点验证数据一致性”)作为提示词(Prompt)输入,请求AI进行分析。
- 用例与脚本生成: AI根据分析结果,生成对应的Postman集合结构(包含文件夹、请求),并为每个请求编写预请求脚本和测试脚本(断言)。
- 输出与集成: 将AI生成的输出转换为标准的Postman Collection v2.1格式的JSON文件,直接导入Postman即可使用。
这个流程的关键在于 提示词工程 。你需要教会AI如何像一个经验丰富的测试工程师那样去思考。例如,不能仅仅让它“生成登录接口的测试”,而应该指令它:“请为登录接口生成三个测试用例:1. 使用正确用户名密码,断言状态码为200,响应体包含 token 字段且不为空,并将 token 值存入环境变量 auth_token ;2. 使用错误密码,断言状态码为401,错误信息字段匹配;3. 请求体缺失用户名,断言状态码为400。”
3. 实操搭建:从零构建你的AI测试助手
3.1 环境与依赖准备
这个方案不依赖复杂的部署,核心是编写一个脚本(Python或Node.js均可)作为桥梁。我以Python为例,因为它处理JSON和HTTP请求非常方便。
基础环境:
- Python 3.8+
- 一个可用的DeepSeek API密钥(从官方平台获取)。
- Postman桌面版(用于导入和运行生成的集合)。
安装必要的Python库:
pip install requests python-dotenv
requests: 用于调用DeepSeek API。python-dotenv: 用于管理API密钥等敏感信息,避免硬编码在脚本中。
项目结构规划:
ai_postman_generator/
├── .env # 存储DEEPSEEK_API_KEY
├── config.py # 配置文件
├── prompt_templates/ # 存放不同场景的提示词模板
│ ├── basic_assertion.j2
│ ├── auth_flow.j2
│ └── data_driven.j2
├── generators/
│ ├── collection_generator.py # 核心生成器
│ └── postman_exporter.py # 导出为Postman JSON
├── input/ # 存放输入的接口文档
│ └── user_api.md
└── main.py # 主执行脚本
3.2 核心脚本编写:与DeepSeek对话
首先,在 .env 文件中配置你的密钥:
DEEPSEEK_API_KEY=your_deepseek_api_key_here
然后,我们编写一个核心的对话函数。这里的关键是构建一个 系统提示词(System Prompt) ,来定义AI的角色和能力。
generators/collection_generator.py 核心片段:
import os
import requests
import json
from dotenv import load_dotenv
load_dotenv()
class DeepSeekClient:
def __init__(self):
self.api_key = os.getenv('DEEPSEEK_API_KEY')
self.base_url = "https://api.deepseek.com/v1/chat/completions" # 请以DeepSeek官方最新API地址为准
self.headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
def generate_test_scripts(self, api_description, test_scenarios):
"""
根据API描述和测试场景,生成Postman测试脚本。
:param api_description: str, 接口的详细描述,包括URL、方法、请求体/参数、响应示例。
:param test_scenarios: list, 测试场景列表,如 ['成功登录', '密码错误', '用户名缺失']
:return: dict, 包含生成的请求和测试脚本的字典。
"""
# 构建一个强大的系统提示词
system_prompt = """你是一名资深的API测试开发工程师,精通Postman和JavaScript。你的任务是根据提供的接口文档和测试需求,生成可直接导入Postman使用的、完整的测试用例。
输出要求:
1. 你必须以纯JSON格式回应,且只包含这个JSON对象,不要有任何额外的解释、标记或代码块包裹。
2. JSON结构必须严格遵循以下示例:
{
"collection_name": "生成的集合名称",
"requests": [
{
"name": "测试用例名称,如: 登录-成功场景",
"method": "GET/POST/PUT等",
"url": "完整的请求URL,包含路径参数。使用{{base_url}}作为环境变量占位符。",
"request_body": {}, // JSON格式的请求体,如果没有则为null
"query_params": {}, // 查询参数对象
"headers": {
"Content-Type": "application/json"
// 其他必要头部
},
"pre_request_script": "// JavaScript代码,用于请求前准备,如生成随机数据",
"tests": "// JavaScript代码,即Postman的Tests脚本,包含pm.test断言"
}
]
}
3. 在`tests`字段中,你必须编写全面且健壮的断言,至少包括:
- 验证HTTP状态码 (pm.response.to.have.status)
- 验证响应时间在合理范围内 (pm.expect(pm.response.responseTime).to.be.below(2000))
- 验证响应体包含必要的字段 (pm.response.to.have.jsonBody, pm.expect(jsonData.field).to.eql(...))
- 对于成功操作,如果返回了认证token或ID等,需要将其保存到环境变量中 (pm.environment.set)
- 验证响应JSON Schema结构(如果条件允许)。
4. 在`pre_request_script`中,如果需要动态数据(如随机邮箱、未来日期),请生成它。
5. 所有硬编码的测试数据(如用户名、密码)应使用Postman的动态变量(如`{{username}}`)或环境变量占位,并在脚本注释中说明。
"""
user_prompt = f"""
接口文档如下:
{api_description}
请为这个接口生成以下测试场景:{', '.join(test_scenarios)}。
请严格按照上述JSON格式输出。
"""
payload = {
"model": "deepseek-chat", # 根据实际可用模型调整
"messages": [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
"temperature": 0.2, # 低温度保证输出稳定、格式正确
"max_tokens": 4000
}
try:
response = requests.post(self.base_url, headers=self.headers, json=payload, timeout=60)
response.raise_for_status()
result = response.json()
ai_output = result['choices'][0]['message']['content']
# 清理输出,确保是纯JSON
ai_output_cleaned = ai_output.strip()
if ai_output_cleaned.startswith('```json'):
ai_output_cleaned = ai_output_cleaned[7:-3].strip()
elif ai_output_cleaned.startswith('```'):
ai_output_cleaned = ai_output_cleaned[3:-3].strip()
return json.loads(ai_output_cleaned)
except requests.exceptions.RequestException as e:
print(f"调用DeepSeek API失败: {e}")
return None
except json.JSONDecodeError as e:
print(f"解析AI返回的JSON失败,原始内容为:\n{ai_output}")
return None
注意: 上面的
system_prompt是灵魂所在。它详细规定了AI的角色、输出格式和内容要求。temperature参数设置为较低值(0.2),是为了让AI的输出更确定、更符合格式要求,减少随机性。在实际使用中,你可能需要根据DeepSeek API的最新文档调整模型名称和端点URL。
3.3 将AI输出转换为Postman集合
DeepSeek生成的是我们自定义的中间JSON格式,需要将其转换为Postman官方集合格式(v2.1)。这是一个结构化的转换过程。
generators/postman_exporter.py 关键转换函数:
def convert_to_postman_collection(ai_output, base_env_vars=None):
"""
将AI生成的中间格式转换为Postman Collection v2.1格式。
"""
if base_env_vars is None:
base_env_vars = {}
collection = {
"info": {
"name": ai_output.get("collection_name", "AI-Generated Collection"),
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [] # 这里存放所有请求
}
for req in ai_output.get("requests", []):
postman_item = {
"name": req["name"],
"request": {
"method": req["method"],
"header": [],
"url": {
"raw": req["url"],
"host": ["{{base_url}}"], # 简化处理,实际应解析URL
"path": req["url"].split('?')[0].split('/')[3:] # 示例性解析
}
},
"response": []
}
# 添加Headers
for key, value in req.get("headers", {}).items():
postman_item["request"]["header"].append({"key": key, "value": value})
# 处理请求体
if req.get("request_body"):
postman_item["request"]["body"] = {
"mode": "raw",
"raw": json.dumps(req["request_body"], indent=2),
"options": {"raw": {"language": "json"}}
}
# 处理查询参数
if req.get("query_params"):
# 这里需要将字典转换为Postman的query数组格式,代码略
pass
# **核心:添加预请求脚本和测试脚本**
event_list = []
if req.get("pre_request_script"):
event_list.append({
"listen": "prerequest",
"script": {
"type": "text/javascript",
"exec": req["pre_request_script"].splitlines()
}
})
if req.get("tests"):
event_list.append({
"listen": "test",
"script": {
"type": "text/javascript",
"exec": req["tests"].splitlines()
}
})
if event_list:
postman_item["event"] = event_list
collection["item"].append(postman_item)
# 可以在这里添加一个全局的变量定义(如base_url的占位说明)
# collection["variable"] = [ ... ]
return collection
转换完成后,使用 json.dump 将collection字典写入一个 .postman_collection.json 文件,就可以直接拖入Postman导入了。
4. 高级技巧与场景化应用
4.1 设计高效的提示词模板
直接让AI从零生成一切,有时效果不稳定。我的经验是准备一些“模板”,让AI在模板基础上填充。这能极大提高生成结果的质量和一致性。
示例:针对RESTful CRUD接口的提示词模板 ( prompt_templates/crud_api.j2 )
你正在为标准的RESTful {{resource_name}} 资源接口生成Postman测试集合。
基础URL是: {{base_url}}/api/{{resource_name}}
已知接口规范:
- 创建(POST): 路径 `/`, 请求体: {{create_request_sample}}
- 查询列表(GET): 路径 `/`, 支持分页参数 ?page=1&size=10
- 查询详情(GET): 路径 `/{id}`
- 更新(PUT/PATCH): 路径 `/{id}`, 请求体: {{update_request_sample}}
- 删除(DELETE): 路径 `/{id}`
请生成一个完整的Postman集合,满足以下要求:
1. 为每个端点生成成功场景的测试请求。
2. 为创建(CREATE)和更新(UPDATE)请求,在`pre_request_script`中动态生成测试数据(如随机的`name`和`email`)。
3. 为创建(CREATE)请求的`tests`脚本中,必须将响应返回的`id`保存到环境变量`{{resource_name}}_id`中,以供后续的详情、更新、删除请求使用。
4. 为删除(DELETE)请求执行后,添加一个验证该资源是否已删除的后续GET请求断言(预期404)。
5. 所有断言需包含状态码、响应结构、关键字段值验证。
在脚本中,你可以使用Jinja2等模板引擎来渲染这些提示词,将 {{resource_name}} 等变量替换为实际值,再发送给DeepSeek。这样生成的集合,天然就具备了测试数据的连贯性和依赖性。
4.2 处理复杂断言:JSON Schema与数据关联
简单的状态码和字段存在性断言AI很容易生成。但复杂的业务逻辑断言需要更精细的指导。
场景:验证订单创建后,订单总价等于各商品单价*数量之和。
你可以在给AI的指令中明确写出断言逻辑:
在“创建订单”请求的Tests脚本中,你需要计算请求体中`items`数组里每个商品的`price` * `quantity`之和,并与响应体中`total_amount`字段的值进行比较断言。使用Postman的`pm.response.json()`和数组的`reduce`方法。
AI基于此生成的脚本可能会是:
// 在Tests脚本中
pm.test("订单总价计算正确", function () {
var jsonData = pm.response.json();
var requestData = JSON.parse(pm.request.body.raw);
var calculatedTotal = requestData.items.reduce((sum, item) => {
return sum + (item.price * item.quantity);
}, 0);
pm.expect(jsonData.total_amount).to.eql(calculatedTotal);
});
对于JSON Schema验证 ,你可以要求AI生成类似下面的断言,这比逐个字段检查更健壮:
pm.test("响应符合预定Schema", function () {
var schema = {
"type": "object",
"required": ["id", "status", "created_at"],
"properties": {
"id": {"type": "number"},
"status": {"type": "string", "enum": ["pending", "processing", "shipped"]},
"created_at": {"type": "string", "format": "date-time"}
}
};
pm.response.to.have.jsonSchema(schema);
});
4.3 集成到CI/CD流水线
生成的Postman集合最终要发挥作用,往往需要集成到自动化流水线中。你可以使用Postman的命令行工具 Newman 来运行集合。
我们的AI生成脚本可以扩展,在生成Postman集合JSON的同时,生成一个对应的 newman 运行脚本或 dockerfile 。
扩展 postman_exporter.py ,生成一个简单的运行脚本:
def generate_newman_run_script(collection_filename, environment_filename=None):
script_content = f"""#!/bin/bash
# 使用Newman运行Postman集合
# 安装Newman: npm install -g newman newman-reporter-html
echo "正在运行API测试集合..."
COMMAND="newman run {collection_filename}"
if [ -f "{environment_filename}" ]; then
COMMAND="$COMMAND -e {environment_filename}"
fi
COMMAND="$COMMAND -r cli,html --reporter-html-export ./test-report.html"
eval $COMMAND
# 检查退出码
if [ $? -eq 0 ]; then
echo "所有测试通过!"
exit 0
else
echo "测试失败,请查看报告。"
exit 1
fi
"""
with open('run_tests.sh', 'w') as f:
f.write(script_content)
print("已生成自动化测试运行脚本: run_tests.sh")
这样,在CI/CD流水线(如Jenkins、GitLab CI)中,步骤就简化为:1. 调用你的Python脚本生成最新的Postman集合;2. 执行 bash run_tests.sh 。测试结果和HTML报告会自动生成。
5. 常见问题、避坑指南与效果评估
5.1 AI生成内容的常见问题与调试
在实际使用中,AI生成的内容不会总是完美的。以下是几个我踩过的坑和解决方案:
问题1:AI生成的JSON格式不正确或包含多余文本。
- 原因: 即使有严格的系统提示,AI有时仍会在JSON前后添加解释性文字或标记错误的代码块。
- 解决: 在解析AI响应时,像前面代码所示,加入更健壮的清理逻辑(检查并去除
```json和```)。同时,在提示词中反复强调“只输出JSON,不要任何其他文本”。如果问题持续,可以尝试在用户提示词末尾加上“记住,你的响应必须是且仅是一个有效的JSON对象。”
问题2:生成的JavaScript断言脚本有语法错误或使用了Postman不支持的API。
- 原因: DeepSeek的训练数据可能包含不同版本的Postman或通用JavaScript语法。
- 解决: 在系统提示词中明确指定Postman的沙盒环境支持哪些库(如
pm.*API,lodash,cheerio等)。例如,可以加上:“你编写的JavaScript代码必须在Postman的测试沙盒环境中运行,主要使用pm.expect(基于Chai)和pm.response进行断言。” 生成后,第一件事是在Postman中运行一下语法检查。
问题3:生成的测试数据过于单一或不符合业务规则。
- 原因: AI可能只是简单复制示例中的数据。
- 解决: 在提示词中明确要求动态生成数据。例如:“对于需要邮箱的字段,请在预请求脚本中使用
Math.random()动态生成一个唯一的测试邮箱,如testuser_<随机数>@example.com。” 或者提供更具体的业务规则:“status字段只能从‘active’, ‘inactive’, ‘pending’中取值。”
5.2 效果评估与迭代
引入AI辅助后,如何评估其效果?我主要看几个指标:
- 用例生成速度: 过去手动编写一个包含5个复杂断言用例的请求可能需要15-30分钟。现在,从输入文档到生成可导入的集合,整个过程在2-5分钟内完成。
- 用例覆盖率(广度): AI能快速生成大量正向、反向用例(如参数缺失、类型错误、边界值),覆盖了那些容易被手动测试忽略的“显而易见”的无效场景,提升了测试集的完整性。
- 断言健壮性(深度): 通过精心设计的提示词,AI生成的断言往往比手动编写的更全面,会主动加入响应时间检查、JSON Schema验证等工程师可能因匆忙而遗漏的检查点。
- 维护成本: 当接口变更时,只需更新输入给AI的接口描述文档,重新运行生成脚本即可获得更新的测试集合,维护效率提升显著。
一个真实的对比: 我曾负责一个用户管理模块的测试,包含约12个接口。手动创建完整的Postman集合并编写所有断言,花了近一个工作日。使用初步版本的AI助手后,我将Swagger文档和测试场景描述输入,生成基础集合只用了10分钟。我随后花了1个小时左右检查和微调AI生成的脚本(主要是调整一些业务逻辑断言和动态变量)。整体效率提升了70%以上,而且生成的断言脚本风格一致,可作为团队内的代码规范参考。
5.3 安全与数据脱敏提醒
这是一个至关重要的实践点。在使用AI生成测试脚本时, 绝对不要 将真实的敏感信息(如生产数据库连接串、真实的用户凭证、内部密钥)放入提示词或生成的脚本中。
- 在提示词中使用占位符: 始终使用
{{base_url}},{{api_key}},{{test_user}}这样的占位符。 - 生成后审查: 在将生成的集合导入Postman或提交到代码仓库前,务必人工审查一遍脚本,确保没有意外泄露的硬编码敏感信息。
- 使用Postman环境: 在最终生成的集合中,将所有敏感或可变的配置都指向Postman的环境变量。你的AI生成脚本应该输出一个“干净”的集合,而将具体的变量值留给用户在Postman环境中配置。
将DeepSeek与Postman结合,不是要完全取代测试工程师,而是将工程师从重复劳动中解放出来,去做更有价值的事情——设计更巧妙的测试场景、探索更隐蔽的缺陷、理解更复杂的业务交互。这个过程本身,也是一个不断“训练”和优化你的“AI测试助手”的过程,你给它的提示词越精准,它反馈给你的内容就越实用。从这个角度看,我们每个人都在成为自己工作流的“提示词工程师”,而这,可能就是未来效率提升的常态。
更多推荐

所有评论(0)