做测试这几年,我越来越觉得有两件事最磨人:一是对着接口文档一条条写用例,二是Bug单里缺请求报文,开发回一句“复现不了,先挂着”。后来我把两者的答案都压到了同一个格式上——HAR(HTTP Archive,HTTP事务的存档文件),再写了一个Skill把它变成自动产出:输入一份HAR,自动导出禅道格式的用例表、自动生成带完整请求/响应证据的Bug草稿。这套流程跑起来之后,新需求用例半小时能出,旧版本Bug也不再被“版本限制”卡住。
这篇文章就聊聊这个Skill是怎么设计的,HAR里哪些信息值得提取,怎么映射成禅道用例,以及提Bug时怎么用HAR突破版本限制。如果你也是测试工程师,或者经常和接口排查、用例管理打交道的开发,这篇可以直接照着搭。
1. 先想清楚:HAR 自动化能把哪些重复劳动省掉
1.1 你手里的 HAR 到底包含什么
HAR 本质上是一个 JSON 文件,主流浏览器的开发者工具和常见抓包工具都能导出来。它记录的是“某一段时间里,浏览器/客户端发出的所有 HTTP 事务”。一个标准的 HAR 里,每个 entry 大致长这样:
{ "startedDateTime": "2025-01-16T10:23:45.123Z", "time": 186.5, "request": { "method": "POST", "url": "https://api.example.com/v1/order/create", "headers": [], "queryString": [], "postData": { "mimeType": "application/json", "text": "{\"productId\":\"P10086\",\"count\":2}" } }, "response": { "status": 201, "statusText": "Created", "content": { "mimeType": "application/json", "text": "{\"orderId\":\"O20250116102345\"}" }, "headers": [] }, "timings": { "send": 0.8, "wait": 150.2, "receive": 35.5 } }这些字段看着简单,但对测试来说全是宝。请求的 URL、方法、参数、请求体、响应状态码、响应体、耗时,都在同一个结构里,而且是有时间顺序的。这就是“现场回放”的基础。
1.2 测试工作中的三个高频重复场景
先说场景A:线上反馈了一个问题,用户用的是旧版本,当前测试环境早就升级了,你手上没有旧包,开发也懒得翻历史版本。这时如果用户能导出一份 HAR,你就能直接看到旧版本发出的真实请求长什么样,参数怎么传的、服务端返回了什么。问题定位完全不需要“复现旧版本”,只需要“复现旧请求”。
再说场景B:新需求上线前要补用例,光接口就有四五十个。以前的做法是打开接口文档,复制路径、粘贴参数、写步骤,一条条录入禅道。一套下来大半天。但如果你有完整的操作录制的 HAR,每个请求本身就是一条用例素材,筛选、清洗、映射之后,批量导入禅道,剩下要人工补充的只是业务预期。
然后是场景C:Bug 单里只有一句“点保存没反应”,开发回复“我这边好的啊”。如果你能把 10 分钟前的 HAR 一起贴上,请求参数、响应错误、耗时都清清楚楚,开发自己打开 HAR 看一遍就能复现根因。这就是“提 Bug 不再受版本限制”的实际含义——限制你的是“复现条件”,而 HAR 把条件变成了数据。
1.3 Skill 解决什么、不解决什么
Skill 在这里指的不是某个具体 AI 助手的专有名词,而是一套“技能包”:一个指令说明文件(SKILL.md)加若干解析脚本。它的定位很明确:把“从 HAR 到禅道用例、Bug 草稿”这条链路里所有机械劳动自动化。
它不负责替你判断业务是否合理,也不负责理解响应内容是不是符合预期。它做的是:提取、过滤、映射、模板化。真正需要测试工程师动脑的部分,比如优先级判断、预期结果合理性,Skill 给出候选值,人来拍板。这个边界想清楚,Skill 才不会变成一个“样样都做、样样稀松”的工具,而是真正省时省力的辅助。
2. Skill 骨架设计:一条命令,从 HAR 到禅道
2.1 Skill 的标准结构
我习惯把这类 Skill 放在一个独立目录里,结构如下:
har-to-zentao-skill/ ├── SKILL.md ├── scripts/ │ ├── parse_har.py │ ├── filters.py │ ├── generators.py │ └── cli.py └── templates/ ├── testcase_excel_header.csv └── bug_template.txt其中 SKILL.md 是给 AI 助手的指令说明,告诉它“当用户给了一个 HAR 文件路径时,你要按什么规则处理”。parse_har.py 负责解析 JSON,filters.py 负责过滤噪音请求,generators.py 负责生成用例表和 Bug 草稿,cli.py 把整个过程串成一条命令行。
2.2 输入与输出约定
这个 Skill 的设计遵循“一个输入,两套输出”的原则。
输入很简单:一个 HAR 文件路径,可选参数是产品名、模块名、影响版本。比如:
python cli.py har_dump.har --product "某商城" --module "订单中心" --version "v1.8.2"输出有两套:
- 第一套是用例表,按禅道标准的 Excel 导入模板生成,人工确认字段后直接导入。
- 第二套是Bug 草稿目录,每个候选 Bug 生成一个 Markdown/TXT 文件,里面已经填好标题、重现步骤、实际结果、预期结果,并标注要附带的 HAR 裁剪片段。
2.3 SKILL.md 的核心指令片段
SKILL.md 不需要写几百行,关键是告诉 AI 助手“什么时候调脚本、按什么原则筛选、生成什么文件”。我写的核心指令类似这样:
# HAR to ZenTao Skill 用户提供 HAR 文件路径时,执行以下流程: 1. 用 scripts/cli.py 解析该文件,默认开启 --auto-filter 参数。 2. 过滤规则:删除静态资源(图片、样式、脚本、字体、媒体),删除埋点/统计域名,保留 XHR/fetch 与文档请求。 3. 对所有保留的 entry 生成候选用例:标题、步骤、预期结果按 templates/testcase_excel_header.csv 的列映射。 4. 对 status >= 400 或 time > 默认阈值的 entry,额外生成 Bug 草稿,放入 output/bugs/ 目录。 5. 输出完成后,向用户说明生成文件路径,并提示人工检查优先级和预期结果。AI 助手看到这个指令,不需要“理解”整个测试流程,只需要遵循固定流程调用脚本、汇总结果。这样 Skill 的可复现性才会高,换一个项目也能用。
3. 从 HAR 到测试用例:筛选规则与字段映射是关键
3.1 第一步:过滤掉噪音请求
一份真实操作流程的 HAR,通常有上百甚至三百个请求。如果不过滤,生成的“用例”大多在测图片加载、字体下载、统计上报,这种用例没人想看,也不可能导入禅道。
我的 filters.py 里第一层过滤是按响应类型过滤:
SKIP_MIME_PREFIX = ( "image/", "text/css", "application/javascript", "font/", "video/", "audio/", "application/octet-stream", ) def is_static_resource(entry): mime = entry.get("response", {}).get("content", {}).get("mimeType", "") return mime.startswith(SKIP_MIME_PREFIX)第二层过滤是按域名过滤。很多业务系统都会带第三方统计、日志上报、崩溃收集、CDN 资源。这些域名的请求对业务用例没有价值。可以维护一个“跳过域名后缀”的配置列表:
-analytics.com -logger. -metrics. -cdn. -static.第三层是按协议类型过滤。有些 HAR 里除了 XHR,还有 WebSocket 升级请求、图片预取、预连接(如 Chrome 的 HTTP/2 连接预协商)。这些也建议直接跳过,因为它们不是可操作的业务接口。
我跑过的真实数据里,三层过滤之后,300 个请求通常只剩 20 到 50 个,留下的大多才是真正需要关注的业务接口。
3.2 第二步:挑选“值得转用例”的事务规则
过滤完噪音后,也不是每个请求都要转用例。我整理了一个优先级规则,按以下顺序决定一个 entry 是否值得转:
| 规则 | 处理方式 |
|---|---|
| status >= 400 | 必须转用例,同时进入 Bug 候选 |
| time > 500ms(wait 阶段) | 强烈建议转用例,重点关注性能回归 |
| 请求方法为 POST/PUT/DELETE/PATCH | 默认全部转用例,涉及状态变更 |
| GET 请求 | 结合响应时间与域名保留,接口型 GET 也转 |
| 重复请求(同 URL+同参数) | 只保留第一个,后续标记去重 |
这里有个容易忽略的点:time字段是总耗时,但用户体验关注的是timings.wait,也就是服务端处理时间。如果wait > 500ms,即使整体time不高,也值得单独拉一条“性能观察用例”。我在脚本里把这两个字段同时输出到用例备注列,方便后续排查。
3.3 第三步:用例字段怎么从 HAR 映射出来
禅道导入用例,核心字段就几个:用例标题、优先级、用例类型、前置条件、步骤、预期结果、关键词。映射逻辑如下:
- 用例标题:拼接
[HAR] HTTP方法 + URL路径 + 状态码。例如[HAR] POST /v1/order/create 201。如果是 4xx/5xx,加异常场景前缀。 - 优先级:建议先全给“中”,人工过一遍再调高调低。自动化做不到判断业务优先级,保守策略比“猜一个高优先级”更稳妥。
- 用例类型:功能测试。如果响应时间超阈值且状态 2xx,可以标记为“性能测试”。
- 前置条件:默认写“用户已登录系统,并处于可触发该请求的页面/状态”。
- 操作步骤:固定三段式——1) 打开被测功能入口;2) 执行触发该请求的操作,可先清空浏览器缓存或重启 App;3) 观察网络请求及响应。
- 预期结果:优先回答两个点:状态码符合预期、响应关键字段符合约定。比如“接口返回 201,响应中包含 orderId 字段”。
这里有个经验:预期结果不要写“请求成功”这种空话。HAR 里如果能看到响应体,就把核心字段和值写进去,比如“响应字段 status=1,message=创建成功”。
3.4 用例 Excel 导出(禅道可导入的模板列)
禅道的批量导入通常走 Excel。我生成的用例表的列头保持和平台导入模板一致,方便直接导入。常见模板列包括:
| 所属产品 | 所属模块 | 用例标题 | 优先级 | 用例类型 | 适用阶段 | 前置条件 | 步骤 | 预期结果 | 关键词 |
|---|
在 generators.py 里,我会把每个事务转成一行 CSV,再做一次文本清洗。特别要注意:步骤和预期结果里如果包含逗号、换行、双引号,CSV 必须做转义,否则导入时会断列。这是我的脚本里最早遇到的坑,先用csv标准库自带的 quoting 参数能一次性解决。
4. 提 Bug 不再受版本限制:把 HAR 变成“现场存档”
4.1 为什么 Bug 会因为版本限制被卡住
版本限制说白了就是“复现环境对不上”。常见情况有:
- 用户用旧版 App,当前测试包是最新版,旧版接口已经改版,测试环境复现不了。
- 线上配置、数据和测试环境不一样,测试环境没有对应的订单状态。
- 需要特定账号、特定地区、特定手机型号才能触发,测试组很难造出同样的条件。
在这些情况下,开发和测试来回拉扯的焦点其实是“请求到底长什么样”。如果你能拿出当时的完整请求数据,问题就从“能否复现”变成了“是否合理”,整个 Bug 流转会顺畅很多。
4.2 HAR 作为现场证据的优势
HAR 的不可替代性在于它同时包含请求和响应,而且自带时间线和耗时。它就像事故现场的行车记录仪:调用了哪个地址、带了什么参数、服务器回了什么、用了多少毫秒,全部留痕。
不过,直接甩一个几百KB甚至几MB的 HAR 文件在 Bug 单里,开发体验很差。打开要半天,还会混入大量无关请求。更好的做法是裁剪后再附上。我在 Skill 里专门做了一个“Bug 关联 HAR 裁剪”功能:根据候选 Bug 的 URL,把原始 HAR 里和它同域名的相关请求抽取出来,生成一个几十KB的片段,并改名为bug_关联接口_时间戳.har。这样开发拿到手就能直接查,不会被无关数据干扰。
4.3 自动生成 Bug 草稿的字段逻辑
对于每个“异常候选”,Skill 会生成一个 Bug 草稿,核心字段映射如下:
| Bug 字段 | 生成逻辑 |
|---|---|
| Bug 标题 | [异常] 接口 + 状态码 + 简述,例如[异常] POST /v1/pay/confirm 500 支付确认失败 |
| 严重程度 | 状态码 5xx 默认“严重”,4xx 默认“一般”,人工可再调 |
| Bug 类型 | 5xx 计为“代码错误”,4xx 计为“接口/参数问题” |
| 重现步骤 | 1) 使用指定账号登录;2) 按 HAR 记录的顺序执行操作;3) 观察返回状态码及内容;并注明“完整请求数据见附件 HAR 片段” |
| 实际结果 | 原样摘录 HAR 响应状态、错误码、响应体前几百字符 |
| 预期结果 | 结合 2xx 同类请求推断,或标记“需确认接口约定” |
其中“预期结果”需要谨慎。如果同一接口在其他事务里返回过成功,我直接拿那个成功响应体做预期参考;如果没有任何成功样本,就明确写“预期应返回 2xx,具体响应需开发确认”,避免把一个猜测值当结论传导给开发。
4.4 附带 HAR 附件的最佳实践
HAR 文件里有 header 里的 Cookie、token 等敏感信息,直接发给开发其实有泄漏风险。我在裁剪脚本里加了一个脱敏开关,默认把cookie、authorization、token、sessionid这几个 header 的值替换成***。这个习惯建议所有做同类工具的人都加上。
脱敏之后,再附带一条说明:如需完整 header 可私信单独提供,避免把敏感凭证长期留在 Bug 系统里。这条我吃亏过——一次把用户 token 直接贴进评论里,后来被安全同事提醒才发现,好在不是线上 token。
5. 跑通流程后的参数微调与常见坑
5.1 过滤规则要按项目定制
我在不同项目里用同一个 Skill,效果差异很大,原因是“静态资源”和“统计域名”每个项目都不一样。现在脚本把这两类配置单独放 JSON 文件里,新项目先跑一次,看日志里哪些请求被过滤掉,再调整配置。
这里有一个非常实用的技巧:第一次解析 HAR 时,把被过滤的请求也输出到一个filtered_log.csv,人工瞄一眼就知道过滤规则是否过重或过轻。有些项目的“接口域”是二级域名,有些是路径前缀,找到特征后配置成正则,过滤准确率能到九成以上。
5.2 重复请求去重与去抖
实际录制 HAR 时,一个页面可能因为 hover、滚动、组件重挂,触发 N 次完全相同的请求。如果不去重,用例表里会出现一大堆重复标题。我的去重键是method + url + 请求体 hashCode。
这里要注意:有些请求体的字段顺序每次不一样,但内容一样,直接 hash 会产生误判。稳妥做法是先把请求体 JSON 解析后sort_keys=True再序列化,然后再 hash。这样处理之后,重复请求能压缩掉一半左右。
5.3 压缩响应体与乱码问题
HAR 里响应体如果来源于压缩传输,导出的文本可能是乱码。我在解析时先看response.content.encoding,遇到 base64 或缺失文本的情况,优先尝试解码,解不出来就只保留状态码、mimeType 和响应大小,不强行摘取内容。
生成 Bug 草稿时,响应体摘取我限制在 500 字符以内。摘太长,Bug 单会被日志刷屏,开发真正要看的是错误码、错误消息和关键字段。
5.4 不同抓包来源的 HAR 差异
浏览器开发者工具导出的 HAR、PC 端抓包工具导出的 HAR,字段结构基本一致,但细节有差异,比如timings是否完整、content.text有无截断、postData.text是否为空。我踩过的坑是:某次从抓包工具导出的 HAR 里的请求体在postData.params里,而不是postData.text。
所以解析脚本里加了一个兼容层:postData里如果text为空但有params,就用params组装请求体。这个小兼容救过我好几次。
5.5 我在实践中得出的参数建议表
最后给一套我实测下来比较稳的参数,直接抄作业即可。
| 参数 | 建议值 | 说明 |
|---|---|---|
| 静态资源 MIME 前缀 | image/, text/css, application/javascript, font/, video/, audio/ | 按项目可增加application/wasm |
| 跳过的域名后缀 | analytics, logger, metrics, cdn, static | 用正则做子串匹配,避免误杀 |
| 耗时阈值 | wait > 500ms 或总 time > 800ms | 低于此值正常不关注,除非项目对性能有硬指标 |
| Bug 候选规则 | status >= 400 或 wait > 1500ms | 5xx 和超长等待是 Bug 高发区 |
| 响应体摘录长度 | 500 字符内 | 防止 Bug 描述变成日志粘贴 |
| 脱敏 header | cookie, authorization, token, sessionid | 默认开启,必须有 |
| 去重键 | method + url + 排序后请求体 hash | 避免误判字段顺序不同的相同请求 |
这些参数没有绝对标准,但以上数值在多个 Web 项目、客户端接口测试场景里都适用。项目规模越大、接口越多,越值得把这套东西沉淀成团队共用的 Skill,而不是每次手工来一遍。
===
最后说点实际体会:这个 Skill 我刚开始搭的时候,解决的问题不是“我不会写 Python”,而是“我懒得定义规则”。因为人工处理 HAR 时,很多判断是凭直觉的——“这个接口有意义,这个没有”。一旦要把直觉变成脚本规则,就得逼自己回答:什么算有意义?字段怎么对应?哪些错误值得提 Bug?这个过程本身就是在帮团队把测试经验标准化。
自动化之后,单个 HAR 从解析到生成用例表、Bug 草稿,耗时基本在几秒到十几秒,相比过去两三小时的重复劳动,提升是很明显的。最让我意外的是,这个 Skill 最大的受益者不是用例产出速度,而是每次 Bug 单“附上裁剪后的 HAR 片段”之后,开发定位问题的速度肉眼可见地变快了。版本环境复现不了的老问题,也随之淡出了争议。