做测试这行,谁没被“提 Bug 填字段”烦过?登录禅道、选产品、选模块、选版本、写复现步骤、粘接口信息……一套流程走下来,几分钟就没了,遇到那种多版本并行、版本列表常年没人维护的项目,光在“影响版本”下拉框里找对那一项就够让人头疼的。后来我发现,浏览器开发者工具导出的 HAR 文件里,其实躺着完整的请求和响应记录——URL、请求参数、返回内容、时间线全都有。我就想,能不能让这玩意儿自己变成禅道里的用例和 Bug?
于是就有了今天这套东西:解析 HAR 文件,提取关键请求,自动生成标题、复现步骤、实际结果,再通过禅道 API 一把梭提交建用例、提 Bug。版本字段的问题,也通过脚本自动获取或创建版本解决了。这篇文章就把整条链路的思路、踩坑过程和一键封装成 Skill 的实操步骤全部摊开来讲,适合正在被重复性用例维护和 Bug 录入折磨的测试工程师,也适合想做测试提效脚本的测试开发同学。
1. HAR 和禅道为什么会成为测试提效的黄金组合
1.1 先搞清楚 HAR 到底是个什么文件
HAR 的全称是 HTTP Archive Format,简单说就是一个 JSON 文件,记录了浏览器和服务器之间发生的每一次 HTTP 请求和响应。你打开 Chrome 开发者工具,切到 Network 面板,随便点点页面,里面那一行行请求就是 HAR 要记录的东西。右键任意请求,选择“Save all as HAR with content”,就能导出一个包含完整内容的 HAR 文件。
这个文件的结构不复杂,最外层是log,下面有entries数组,每一个 entry 就是一条请求记录。每条记录里又拆成了request、response、timing这些块,请求头、响应头、请求体、响应体、状态码、耗时全都有。响应体如果特别大,可能会被转成 Base64 编码存在content.text里,解析的时候要先解码。
我用一个生活化的类比去解释它:HAR 就像行车记录仪,把请求从出发到返回的全过程都拍下来了,什么时候发出去、发了什么内容、服务器回了个什么结果,一目了然。测试人员做 Bug 定位的时候,最缺的就是这种完整证据链。以前我们常要截图、复制接口返回、记录操作步骤,现在 HAR 一次性把这些全部打包了。
1.2 禅道建用例、提 Bug 的老痛点
禅道在国内测试团队里的使用率相当高,用例库、Bug 跟踪、测试任务都在上面维护。但用久了就会发现,它功能全归全,手工录入的成本也被很多团队忽略了。
先说建用例。一个标准用例要填产品、模块、标题、前提条件、步骤、预期结果。模块管理得细的项目,光找模块就要点半天。很多用例的步骤其实是同一套操作模板换几个参数,比如登录、查询、提交、导出,每次手工复制粘贴改一改,枯燥且容易错。
再说提 Bug。新建 Bug 必填的字段里有产品、模块、标题、严重程度、优先级,还有一个最麻烦的“影响版本”。这个版本字段,业务上指的是当前测试的这个构建或发布版本。理论上它应该对应产品计划里已经维护好的版本号,但实际情况是什么呢?有人用敏捷迭代,版本号用日期或者迭代编号,禅道上根本没建对应的构建;有人并行测试多个版本,下拉列表里全是旧版本,选哪个都觉得不对;更极端的情况是产品模块刚初始化,版本列表完全是空的,Bug 想提都提不了,只能先停下来说“帮我加个版本”。
这个“版本限制”,本质上是禅道 Bug 表的version字段非空校验,同时这个字段又必须关联已存在的构建。只要版本列表没跟上研发节奏,测试提 Bug 就会被硬生生卡住。这也是我做这套自动化时重点想解决的问题。
1.3 这套自动化方案的定位和适用范围
这套链路简单描述就是:拿一个 HAR 文件进去,出来的是禅道里可用的用例和 Bug 草稿。HAR 里全是真实的数据,所以生成的 Bug 复现路径有根有据,再也不用人工回忆“刚才那个请求是怎么发的”。脚本负责脏活累活,人负责判断和确认。
它特别适合两类场景。第一类是 Web 功能测试,尤其是接口报错类的缺陷,比如提交订单返回 500、列表接口超时、某个按钮点击后请求参数不对,这类问题 HAR 里记录得非常清晰。第二类是接口联调阶段,前后端配合出现异常,直接导出 HAR 就能把失败请求及相关参数送到禅道上,作为缺陷依据。
但要注意,它不适合纯前端不产生网络请求的 UI 问题,比如样式错乱、文案显示不全,这种问题 HAR 帮不上忙,还是得靠截图和录屏。另外,如果 HAR 里全是静态资源请求,也需要过滤后才有价值。
2. 整体设计思路:一条链路怎么打通
2.1 从 HAR 到 Bug 和用例的数据映射
打通流程的第一步,是搞清楚 HAR 里的字段到底能对应到禅道的哪些字段。这不是随便拼凑,而是要理解禅道创建 Bug 和用例时,到底需要哪些信息。
我列了一张我自己项目里一直用的映射表:
| HAR 字段 | 禅道 Bug/用例字段 | 用途说明 |
|---|---|---|
| entry.request.method + url | 复现步骤的第一步 | 明确接口调用方式 |
| entry.request.postData | 前置条件/复现参数 | 展示请求体参数 |
| entry.response.status | 实际结果 | 缺陷表现为状态码 |
| entry.response.content.text | 实际结果补充 | 展示后端返回的具体报错 |
| entry.startedDateTime | 复现时间 | 辅助定位日志 |
| 自定义规则提取的业务信息 | 标题 | 比如从接口路径提炼操作名 |
| 模块配置 | 模块 | 脚本通过规则自动匹配模块 |
这个映射思路的核心是:每一个生成的字段都来自真实请求,而不是凭空想象。比如标题字段,我不会直接拿 URL 当标题,那太长了。更合理的做法是从 URL 中匹配业务关键词,比如/api/order/create匹配到“订单创建”,然后用“下单接口返回 500 导致订单创建失败”这种组合方式生成。规则可以用配置文件维护。
2.2 为什么要写成一个 Skill 而不是临时脚本
一开始我也只是写了个临时 Python 脚本,处理单个 HAR 文件。但用了两天就发现,这个流程真正有价值的地方在于可复用。于是我把整个流程重构成一个独立的自动化技能包,英文叫 Skill。我理解的 Skill,就是把一个特定业务场景下的自动化能力封装成可配置、可复用、可组合的模块。
举个具体例子。一个 Skill 包里至少要有三部分:HAR 解析器、禅道 API 客户端、模板生成器。再配合一个config配置文件,把禅道地址、默认产品、默认模块、过滤规则都写在配置里。这样团队里任何一个人拿过来,只要改一下配置,就能生成适合自己的用例和 Bug。
为什么不直接用临时脚本?因为临时脚本的代码和测试同学强绑定,换个人就要重新读代码、改逻辑。而封装成 Skill 后,使用方式固定为一条命令或者一个按钮,新同学不用关心内部实现。尤其是当这个过程要接入持续集成、或者提供给多个测试小组共用的时候,模块化带来的好处会非常明显。
技术选型上我用了 Python。原因很简单:requests 库做 HTTP 调用很顺手,标准库的 json 足够处理 HAR 文件,整体代码量可控。团队里测试开发几乎都会 Python,后续改起来不愁找不到人。
2.3 解决“版本限制”的关键思路
这是我做这套自动化时最想解决的点。禅道创建 Bug 时,影响版本是必填项,但测试人员的痛点往往就出在这个必填上。版本列表缺失、版本号混乱、版本未提前维护,都会导致手工提 Bug 的时候没法往下走。
脚本解决这个问题的思路其实很务实:不依赖人肉从下拉框选版本,而是由程序自动处理版本。
实际操作上我分三种情况处理:
- 第一种,禅道里已经有版本列表,就从产品对应的构建列表里挑一个最合适的。合适条件可以配置,比如“取最新的构建”或“取名字匹配某个迭代号的构建”。
- 第二种,版本列表为空,就尝试通过禅道的构建创建接口自动建一个默认版本,名字可以叫“当前测试版本”或者干脆用日期充当版本号。
- 第三种,账号权限不够、创建不了构建,脚本就把版本信息记录到 Bug 描述里,同时给用户一个人工提示,避免提交失败时一头雾水。
这样一来,“版本限制”在自动化层面就被绕开了。人依然在流程中,但不需要再去关注“版本存不存在”这个低价值问题了。版本不管有没有,脚本都能保证 Bug 成功创建,顶多提示你手动补充一下版本说明。
3. 实操:HAR 一键生成禅道用例和 Bug
3.1 环境准备和 Skill 目录结构
开始动手前,先把环境备好。我是用 Python 3.9 做的,依赖很少,核心只需要requests,其他都用标准库。安装命令一条:
pip install requests pyyaml然后从浏览器导出 HAR 文件。这里有个容易踩的坑,Chrome 开发者工具 Network 面板里,如果只是右键单个请求选择“Save as HAR with content”,保存的是单条请求;要保存整个页面的所有网络记录,需要右键任意位置,然后选最后一项“Save all as HAR with content”。一定要确认保存下来的文件是 JSON 数组结构,且里面包含响应内容,否则后面解析的时候拿不到返回值。
我本地的目录结构大概长这样:
skill_har_zentao/ ├── config.yaml # 禅道地址、token、默认配置 ├── har_parser.py # HAR 解析,筛选和提取关键信息 ├── zentao_client.py # 禅道 API 交互 ├── skill.py # 一键执行入口 └── templates/ ├── bug_template.md └── case_template.mdconfig.yaml是第一个要改的文件,我把经常变的配置都放在里面,代码里不硬编码。示范一下配置内容:
zentao: url: "http://your-zentao-server" token: "" # 或者传账号密码自动获取 token default_product: 0 # 默认产品 ID default_module: 0 # 默认模块 ID default_build: "" # 默认版本兜底名称 har: filter_methods: ["POST", "GET", "PUT", "DELETE"] filter_status_codes: [400, 401, 403, 404, 500, 502, 503] filter_keywords: ["/api/", "/rest/"] # 只保留符合业务特征的请求 max_entries: 200 # HAR 太大时限制解析条数 rule: # URL 路径匹配正则到业务名称,用于自动生成标题 business_keywords: "/api/order/create": "订单创建" "/api/user/login": "用户登录"配置里最核心的是filter_keywords和business_keywords,前者决定哪些请求会被挑出来,后者决定标题怎么命名。一开始我没配这两个规则,结果 HAR 里一堆图片、CSS、字体请求全被当成缺陷提交,把禅道搞得乌烟瘴气。
3.2 核心代码:解析 HAR 并找出有问题的请求
解析工作其实分两步:读文件、找有用的请求。我写了一个har_parser.py,核心逻辑是遍历 HAR 的 entries,取出每个请求的方法、URL、请求体、状态码、响应体,然后用配置的规则去过滤。
直接看代码:
import json import base64 import logging def load_har(file_path): with open(file_path, "r", encoding="utf-8") as f: return json.load(f) def extract_entries(har): return har.get("log", {}).get("entries", []) def is_relevant(entry, config): method = entry.get("request", {}).get("method", "") url = entry.get("request", {}).get("url", "") status = entry.get("response", {}).get("status", 0) if method not in config["har"].get("filter_methods", []): return False if status not in config["har"].get("filter_status_codes", []): return False if not any(k in url for k in config["har"].get("filter_keywords", ["/api/"])): return False return True def extract_request_info(entry): req = entry.get("request", {}) res = entry.get("response", {}) post_data = req.get("postData", {}).get("text", "") content = res.get("content", {}) content_text = content.get("text", "") # HAR 的响应内容可能是 Base64 编码 if content.get("encoding") == "base64": content_text = base64.b64decode(content_text).decode("utf-8", errors="ignore") return { "method": req.get("method"), "url": req.get("url"), "post_data": post_data[:1000], # 截断超长请求体 "status": res.get("status"), "response_text": content_text[:2000], # 截断响应体 "started_datetime": entry.get("startedDateTime") } def parse_har(file_path, config): har = load_har(file_path) entries = extract_entries(har) extracted = [] for entry in entries: if is_relevant(entry, config): extracted.append(extract_request_info(entry)) if len(extracted) >= config["har"].get("max_entries", 200): break return extracted这段代码里做的三件事正好对应前面说的三个思路:过滤掉静态资源请求、提取关键请求数据、限制解析量防止超大 HAR 文件拖垮脚本。
实际用得多了,我发现失败状态码的过滤条件要谨慎。有些接口虽然返回 200,但业务逻辑里是失败的,比如响应 JSON 里code: 1表示业务异常。所以后期我又加了一个判断:如果响应内容里包含"error"或"exception"等关键字,也视为候选 Bug 请求。这个在真实测试场景里命中率还挺高。
3.3 核心代码:用禅道 API 创建用例和 Bug
拿到提取出来的请求信息后,下一步就是和禅道通信。禅道提供了两套 API,老一点的叫 JSON-RPC,新一点的叫 RESTful v1。我建议优先用 RESTful v1,路径清晰、参数直观。不过要注意,禅道的 REST API 默认不一定开启,需要在后台“自定义-API”里把开关打开。
先看登录拿 token。早期版本用账号密码直接调用接口换取会话,现在更推荐先在禅道后台生成永久 API token,然后每次请求带上。
import requests class ZentaoClient: def __init__(self, url, token): self.base = url.rstrip("/") self.token = token self.session = requests.Session() self.session.headers.update({ "Content-Type": "application/json", "X-ZTA-SESSION": token, # 部分版本通过这个头传递 token "Token": token # 部分版本通过这个头传递 token }) def get_products(self): resp = self.session.get(f"{self.base}/api.php/v1/products") resp.raise_for_status() return resp.json()["products"] def get_builds(self, product_id): resp = self.session.get(f"{self.base}/api.php/v1/products/{product_id}/builds") resp.raise_for_status() return resp.json().get("builds", []) def create_build(self, product_id, name, builder="测试脚本"): payload = { "product": product_id, "name": name, "builder": builder, "date": "2026-05-01" # 换成实际日期 } resp = self.session.post(f"{self.base}/api.php/v1/products/{product_id}/builds", json=payload) return resp.status_code in (200, 201)创建 Bug 的接口路径是POST /api.php/v1/bugs。参数里最核心的是product、title、steps、version、severity、pri。其中steps是一个 HTML 字符串,禅道会在 Bug 详情页直接渲染出来。我把 HAR 里提取到的请求信息拼成这个 HTML。
def build_steps_html(request_info): return ( "<p>复现步骤:</p>" f"<p>1. 打开被测页面,触发接口请求 {request_info['method']} {request_info['url']}</p>" f"<p>2. 观察接口返回状态码为 {request_info['status']}</p>" "<p>实际结果:</p>" f"<pre>{request_info['response_text']}</pre>" "<p>期望结果:</p>" "<p>接口应返回成功,业务流程正常完成。</p>" ) def create_bug(client, product_id, title, steps_html, build_id): payload = { "product": product_id, "title": title, "steps": steps_html, "version": build_id, "severity": 2, # 严重级别,按需调整 "pri": 1, # 优先级,按需调整 "type": "codeerror" } resp = client.session.post(f"{client.base}/api.php/v1/bugs", json=payload) if resp.status_code in (200, 201): return resp.json() raise RuntimeError(f"创建 Bug 失败: {resp.text}")创建用例和创建 Bug 大体类似,接口地址是POST /api.php/v1/testcases,步骤字段steps是更结构化的 JSON,不是 HTML 字符串。我按禅道的规范组装:
def create_testcase(client, product_id, module_id, title, request_info): steps = [ { "type": "step", "desc": f"访问 {request_info['method']} {request_info['url']},携带参数 {request_info['post_data']}", "expect": "接口返回成功,业务结果正确" } ] payload = { "product": product_id, "module": module_id, "title": title, "steps": steps, "pri": 1 } resp = client.session.post(f"{client.base}/api.php/v1/testcases", json=payload) resp.raise_for_status() return resp.json()这里有个坑必须提醒:创建 Bug 和创建用例都要传产品 ID,但产品 ID 不是产品名字。我一开始直接在配置文件里填产品名,脚本老报错。先在禅道后台打开产品列表,把产品 ID 数字记下来,再填到config.yaml里。如果产品很多,也可以先用client.get_products()打印一下,核对清楚再写。
3.4 版本字段的自动化处理逻辑
前面反复强调“版本限制”,现在把代码层面的处理逻辑完整写出来。核心思路是三步走:先查已有版本,没有就创建默认版本,再不行就在描述里附带版本说明。
def ensure_build(client, product_id, config): builds = client.get_builds(product_id) if builds: # 优先取名字匹配最新迭代的构建,否则直接取第一个 return builds[0]["id"], builds[0]["name"] default_build_name = config["zentao"].get("default_build", "当前测试版本") create_success = client.create_build(product_id, default_build_name) if create_success: new_builds = client.get_builds(product_id) return new_builds[0]["id"], new_builds[0]["name"] else: # 没有权限创建构建,就返回一个占位 ID,同时警告用户 return None, default_build_name build_id, build_name = ensure_build(client, product_id, config) if build_id is None: # 把版本信息拼到步骤 HTML 里,或者单独打印警告 print(f"警告:无法获取或创建构建,请手动到禅道添加版本后再提交") else: create_bug(client, product_id, title, steps_html, build_id)这个逻辑是“不再受版本限制”的落地实现。用户不需要知道当前有哪些版本,脚本会自己查、自己建、自己兜底。我在真实项目里遇到过那种版本列表完全是空的场景,靠这个逻辑直接自动创建了一个“当前测试版本”,Bug 提交一次就成功了。事后产品经理还很惊讶为什么禅道里多了个构建,我解释说是脚本建的,他反而觉得方便。
3.5 一键执行入口:把流程串起来
有了解析器、API 客户端和版本处理逻辑,最后写一个skill.py把整条流程串起来,实现真正意义上的“一键”。
import yaml import argparse from har_parser import parse_har from zentao_client import ZentaoClient def load_config(path="config.yaml"): with open(path, "r", encoding="utf-8") as f: return yaml.safe_load(f) def auto_title(request_info, config): # 用业务关键词规则自动生成标题 for keyword, biz_name in config["rule"]["business_keywords"].items(): if keyword in request_info["url"]: return f"{biz_name}接口异常:{request_info['method']} {request_info['url']} 返回 {request_info['status']}" return f"接口异常:{request_info['method']} {request_info['url']} 返回 {request_info['status']}" def main(): parser = argparse.ArgumentParser(description="HAR 一键生成禅道用例和 Bug") parser.add_argument("--har", required=True, help="HAR 文件路径") parser.add_argument("--product", type=int, default=0, help="产品 ID") parser.add_argument("--mode", choices=["bug", "case", "both"], default="both") args = parser.parse_args() config = load_config() product_id = args.product or config["zentao"]["default_product"] client = ZentaoClient(config["zentao"]["url"], config["zentao"]["token"]) build_id, build_name = ensure_build(client, product_id, config) request_infos = parse_har(args.har, config) print(f"从 HAR 中提取到 {len(request_infos)} 条候选请求") for info in request_infos: title = auto_title(info, config) steps_html = build_steps_html(info) if args.mode in ("bug", "both"): create_bug(client, product_id, title, steps_html, build_id) print(f"已提交 Bug:{title}") if args.mode in ("case", "both"): create_testcase(client, product_id, config["zentao"]["default_module"], title, info) print(f"已创建用例:{title}") if __name__ == "__main__": main()这样,使用方式就固定为一条命令:
python skill.py --har ./har_download/20260501_orders.har --product 2 --mode both我在团队里推行的时候特意强调了一点:这个脚本默认是自动提交的,但在大规模使用前,建议先加一个--dry-run参数,只打印将生成的标题和步骤,不做真实提交。确认效果符合预期后,再放开自动提交。防止脚本把一堆无关请求全变成 Bug 刷屏,影响禅道里的数据质量。
4. 常见问题与排查技巧实录
4.1 HAR 文件导出来但解析不到内容
这个我一开始经常遇到。现象是脚本运行后提示提取了 0 条候选请求,或者解析出来全是空字符串。排查方向有这几个:
第一,确认导出的 HAR 是不是“with content”版本。Chrome 里如果用“Save all as HAR”而不是“Save all as HAR with content”,响应体会全部为空,这直接导致后续拿不到实际返回内容。第二,确认 URL 过滤条件。很多 SaaS 产品的接口路径不是/api/开头,可能是/gateway/、/rpc/,如果配置的filter_keywords匹配不上,自然一条都提不出来。第三,HAR 文件本身可能非常大,几百 MB 都存在,解析时内存占用高,可以考虑用max_entries限制解析条数,或者先用工具筛一次,只保留 XHR/Fetch 请求。
我在实际使用中习惯先在 Chrome 网络面板里输入-has:image或者过滤Fetch/XHR类型,把静态资源排除掉再导出,这样 HAR 文件体积小、噪音少,脚本解析效率高。
4.2 禅道 API 报 401 或者权限不足
禅道 REST API 的权限控制比较严,一个核心原因是启没开启 API。后台“自定义-API”里把开关打开之后,还要确认账号有对应产品、项目的访问权限。我踩过的坑是:用管理员账号测试时一切正常,换成一个普通测试账号就报 403,最后发现账号没关联到产品。这个一定要检查。
如果公司禅道版本比较老,不支持 v1 REST API,就回退用老的 JSON-RPC 方式,接口地址一般是/api.php?m=api&f=jsonRpc。使用方式不太一样,参数要走一层包裹,网上资料也不少,但能用新接口尽量用新的。
4.3 创建 Bug 时提示版本不能为空
如果在ensure_build这步没处理到位,仍然会报这个错。最直接的排查方法是看get_builds(product_id)返回的列表里有没有内容,以及返回的build_id是否为None。
有一种容易被忽略的情况:禅道里虽然能看到版本列表,但某些已存在的 build 状态是“正常”还是“终止”会有区别,API 返回的列表可能只包含特定状态的构建。所以不要想当然认为“下拉框里能看到就能通过 API 用”,一切以 API 返回值为准。
如果确实拿不到版本,就回到前面的兜底逻辑:调用create_build尝试创建一个“当前测试版本”。但要注意创建构建可能需要编辑产品或项目的权限,普通测试账号通常会失败,所以我在脚本里把创建失败的结果降级成“警告 + 附带版本说明”,而不是直接报错退出,先把 Bug 提交成功的路径保住。
4.4 生成的步骤太啰嗦,或者全是噪音
这个问题的根源不在代码,在于 HAR 的录制范围。如果录制时页面加载了大量资源、包括各种埋点请求和心跳请求,生成的内容自然会乱。我的经验是:录制 HAR 前,在浏览器 Network 面板过滤出要关注的接口类型,比如只保留Fetch/XHR,或者只保留业务域名。同时把filter_keywords设置严格一点,只匹配业务接口路径。
另外,生成用例和生成 Bug 的定位要区分一下。Bug 需要有“实际结果”和“期望结果”,所以响应体的报错内容很重要;而用例更多关注操作步骤和断言,响应体截断几千字反而没有意义。我在脚本里把这两个场景的字段长度分别做了控制,实际效果比一开始统一处理要清爽很多。
4.5 问题速查表
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 解析到 0 条 | HAR 无 content / 过滤条件过严 | 用 with content 导出,放宽关键词 |
| 提交 Bug 失败 401 | API 未开启 / 账号无权限 | 检查后台 API 开关和产品权限 |
| 版本不能为空 | 版本列表为空 / 无权创建构建 | 检查get_builds返回值,走兜底逻辑 |
| 标题/步骤质量差 | HAR 录制范围太广 | 过滤静态资源,限定业务域名 |
| 脚本内网访问不了禅道 | 网络限制 | 在能访问禅道的内网环境运行 |
5. 我怎么把这个 Skill 集成到日常测试流程里
脚本本身不难写,真正让我觉得有价值的是把它嵌进日常流程之后的变化。我现在处理一个典型的接口报错 Bug,流程是:打开浏览器,操作复现,导出 HAR,运行python skill.py --har xxx.har --product 2 --mode bug,然后就完事了,剩下的时间用来和开发沟通根因。
如果是回归测试阶段,我会用--mode both,一次既建用例也提 Bug。平时用例库里一些系统性的接口用例比较薄弱,用这个方式能很快生成一批带真实参数的用例,后面再让测试同学补充预期结果和业务断言,效率比从零写高了不少。
后面我还在这个基础上加了一个小功能,把生成的 Bug 标题和建议指派给谁做关联,通过配置规则把特定接口对应到特定开发负责人。这样脚本提交 Bug 的时候能直接指派人,省掉了提完还要手动改指派人的一步。虽然改动很小,但每次提交 Bug 都能少点一次鼠标,累积下来还是挺可观的。
这套东西目前我已经用了两个迭代周期,最大的体会是:让自动化去做数据采集和字段填充,把人从重复劳动里解放出来,测试质量反而提高了。以前我提 Bug 时经常会漏写请求参数,因为手动复制容易丢三落四,现在 HAR 解析出来的参数都是完整的,基本没有这种漏写的情况。
如果后面想继续扩展,可以考虑把生成的 Bug 和用例关联起来,比如自动在用例上标记关联的 Bug ID;也可以做一个简单的界面,让测试同学拖入 HAR 文件就能看到解析预览,再点确认提交。不过这些都建立在当前这套链路稳定的基础上。先把一键生成跑通,版本问题解决掉,再谈更多花样。