背景痛点:传统测试的“三座大山”
- 用例维护像“打地鼠”。需求一改,上百条 Excel 用例就要人工对齐,漏改一条就可能把缺陷带到线上。
- 边界场景靠“拍脑袋”。等价类、边界值分析全看测试同学经验,新人写出的用例常常漏掉 0、null、空数组这些“老六”值。
- 日志定位靠“肉眼”。接口一报错,先翻几百行 log,再去找代码,平均定位时间 30 min 起跳,迭代一快就撑不住。
一句话:人力是瓶颈,时间是成本,覆盖是玄学。
技术对比:Selenium 老矣,AI 能否饭否?
| 维度 | Selenium/传统框架 | ChatGPT 辅助测试 |
|---|---|---|
| 用例生产 | 人写,速度线性 | 自然语言秒批,批量生成 |
| 边界覆盖 | 依赖经验 | 模型自带“脑洞”,易补全异常值 |
| 维护成本 | 元素一改,脚本全崩 | 用例文本化,diff 友好 |
| 稳定性 | 浏览器版本、等待时间难控 | 不操作 UI,API 层调用稳定 |
| 执行速度 | 本地毫秒级 | 网络延迟 0.5-2 s,需并发优化 |
| 确定性 | 100% 可预期 | 有概率跑偏,需二次校验 |
结论:AI 不是替代,而是“外挂”。把脏活累活交给模型,人专注策略和验收。
核心实现:让 GPT 替你写用例、跑用例、验用例
1. Prompt 设计模式——“角色 + 任务 + 格式 + 边界”
你是一名资深测试工程师,请为下面接口生成 10 条边界测试用例,覆盖等价类、边界值、异常值。 接口:POST /api/v1/user/login JSON 字段 email, password 输出格式:CSV,字段 用例编号, 描述, 输入, 预期结果把“边界值”“异常值”关键词写进 Prompt,能显著降低遗漏率;再补一句“不要解释,直接给表”,模型就会乖乖闭嘴,只出数据。
2. 调用 OpenAI API 的 Python 脚手架(含异常重试)
import openai, csv, time, os from typing import List openai.api_key = os.getenv("OPENAI_API_KEY") def gpt_generate_cases(prompt: str, model: str = "gpt-3.5-turbo") -> str: """调用 ChatGPT 并返回原始文本,带指数退避重试""" for attempt in range(1, 4): try: rsp = openai.ChatCompletion.create( model=model, messages=[{"role": "user", "content": prompt}], temperature=0.3, # 降低随机性 timeout=20, ) return rsp.choices[0].message.content except openai.error.RateLimitError: time.sleep(2 ** attempt) except Exception as e: print(f"[warn] attempt {attempt} failed: {e}") time.sleep(1) raise RuntimeError("GPT 调用失败,请检查网络或额度") def parse_csv(raw: str) -> List[dict]: """把模型返回的 CSV 字符串解析成列表""" lines = raw.strip().splitlines() return [row for row in csv.DictReader(lines)] if __name__ == "__main__": prompt = open("prompt_login.txt").read() raw = gpt_generate_cases(prompt) cases = parse_csv(raw) print(f"生成用例数:{len(cases)}")要点
- temperature 0.3 足够保守,减少天马行空
- 指数退避避免踩 RateLimit
- 返回 CSV 方便直接落地到 pytest 参数化
3. 测试结果验证——双重断言策略
import requests, pytest @pytest.mark.parametrize("case", cases) def test_login_boundary(case): payload = eval(case["输入"]) # 模型给的是字符串字典 rsp = requests.post(f"{BASE_URL}/user/login", json=payload) # 1. 状态码断言 assert rsp.status_code == 200 # 2. 业务语义断言 expected = eval(case["预期结果"]) if "token" in expected: assert "token" in rsp.json() else: assert rsp.json().get("code") == expected["code"]先码后验:第一层防 5xx,第二层防业务逻辑错;即使 GPT 写错,也能快速暴露。
性能考量:别让 API 等待拖垮流水线
- 并发池:使用
asyncio+aiohttp把 100 条用例拆成 10 并发,延迟从 100×1 s 降到 10 s。 - 缓存:相同接口版本下 Prompt 不变,可把返回结果落盘到
cases_v1.2.json,下次直接读缓存。 - 模型选择:冒烟测试用 gpt-3.5-turbo 即可;核心路径再换 gpt-4,兼顾成本与精度。
- 失败重跑:CI 里加
pytest --lf仅重跑失败项,避免整轮重调 API。
避坑指南:AI 很香,但别“无脑冲”
- 模糊用例:模型可能写“输入超长字符串”却不给具体值。解决:Prompt 末尾加“输入字段必须给出具体值,禁止模糊描述”。
- 敏感数据:禁止把生产密钥贴进 Prompt。用占位符
{{PASSWORD}},生成后再局部替换。 - 版本控制:把 Prompt、生成用例、校验脚本都扔进 Git;接口一变,diff 可见,回滚不慌。
- 随机种子:在 Prompt 里加“随机数种子=42”可让输出在单元测试里可重复,方便回归。
延伸思考:把 AI 测试搬进 CI/CD
GitHub Actions 示例片段:
- name: Generate Test Cases run: | pip install openai python scripts/gen_cases.py > api_cases.json - name: Run Tests run: pytest -n 10 --cases=api_cases.json --html=report.html - name: Upload Report uses: actions/upload-artifact@v3MR 触发 → 自动生成 → 并行执行 → 报告归档,缺陷在合并前就现形。再往前一步,可把“生成 diff → 只针对 diff 生成增量用例”做成脚本,真正实现“测试左移”。
写在最后
把 ChatGPT 当“测试外包”用,你会发现 70% 的重复劳动都能被机器吃掉,但剩下的 30% 策略、验收、调优依旧离不开人。先跑通一个小接口,再把套路复制到单元、API、UI 各层,一条流水线就盘活了。如果你也想亲手搭一个会“听、想、说”的 AI 伙伴,不妨看看这个实验——从0打造个人豆包实时通话AI,我跟着做了一遍,步骤很细,本地 30 分钟就能跑通,对“让 AI 干活”这件事会有更立体的体感。祝你测试不再头秃,缺陷早日清零。