拓冰建站拓冰建站
首页 / 资讯中心 / 正文

AI自动化测试:用Skill固化Web测试经验,告别不稳定脚本

AI 写自动化测试真正难的从来不是“写代码”而是让 AI 知道页面元素该用什么方式定位、等待逻辑怎么写才稳定、断言要对应哪些业务规则、测试报告要输出到什么程度。这些知识靠一长串 Prompt 根本装不下但可以结构化到一个 Skill 里。很多测试同学用 AI 助手时会遇到同样的尴尬生成的脚本第一眼很完整一运行就崩让它改一个定位符它把整个文件重写了让它补一条用例逻辑和页面流程完全对不上。问题不是模型能力不够而是我们没有把“测试这门手艺”的系统知识提供给模型。这篇文章要解决的就是怎么把 Web 自动化测试的领域经验封装成一个可复用的 Skill。我会从一个可以直接照抄的工程讲起覆盖 Skill 的目录结构、完整代码、Markdown 报告模板、运行验证和常见问题排查。读完你能在自己的项目里搭建一套专属的 AI 测试 Skill并理解它背后真正提升效率的机制。1. 这篇文章真正要解决的问题1.1 AI 写自动化测试的常见翻车现场先看几个真实场景。场景一让 AI 写一组登录页测试用例。它很快给出一个 Playwright 脚本看起来逻辑完整有页面打开、输入用户名密码、点击登录、断言跳转。但一运行脚本在第一步就超时了。原因是它生成的是固定的time.sleep(3)页面加载慢一点就崩快一点又白白等三秒。场景二让 AI 定位一个按钮。它给了page.locator(text提交).click()。结果页面上有两处“提交”一个在导航栏一个在表单底部。脚本随机点到了一个不可见元素测试报错。如果团队里有一个懂测试的人他会告诉你优先用get_by_role(button, name提交)或者给按钮加上稳定的>python -m venv .venv source .venv/bin/activate # Windows 使用 .venv\Scripts\activate pip install playwright playwright install chromium这里一定要执行playwright install chromium它会下载 Playwright 需要的浏览器内核。如果跳过这一步脚本运行时会直接报“可执行文件不存在”的错误。3.3 准备一个可测试的本地页面为了不依赖外网环境我们生成一个简单的本地页面。创建demo/index.html!-- 文件路径demo/index.html -- !DOCTYPE html html langzh-CN head meta charsetUTF-8 title测试页面/title style #app { max-width: 600px; margin: 50px auto; font-family: sans-serif; } .status { color: green; font-weight: bold; } /style /head body div idapp h1欢迎使用 AI 测试 Skill/h1 p这是一个用于验证 Web 自动化测试 Skill 的本地页面。/p button idsubmit-btn提交/button input idsearch-input placeholder请输入关键词 / /div /body /html在项目根目录执行python -m http.server 8080然后浏览器访问http://127.0.0.1:8080/看到页面说明本地环境正常。如果不想在本机起服务也可以用公开测试站点但要注意不要对没有授权的站点做高频自动化访问。本地页面是最稳定、最安全的选择。4. 测试 Skill 的目录结构与设计思路4.1 整体目录结构一个 Web 自动化测试 Skill 可以这样组织web-test-skill/ ├── SKILL.md ├── scripts/ │ ├── run_web_test.py │ └── generate_test_case.py ├── examples/ │ └── smoke_test_demo.md ├── docs/ │ ├── best_practices.md │ └── troubleshooting.md └── requirements.txt先建目录mkdir -p web-test-skill/scripts mkdir -p web-test-skill/examples mkdir -p web-test-skill/docs4.2 每个文件的作用SKILL.md是 Skill 的入口AI 会优先读取它。scripts/run_web_test.py是核心执行脚本负责访问页面、检查元素、生成报告。scripts/generate_test_case.py是辅助脚本用于批量生成测试用例 Markdown 骨架。examples/存放调用示例AI 生成新脚本时可以参考。docs/存放最佳实践和排查手册进一步增强 Skill 的知识量。requirements.txt声明 Python 依赖。这种拆分的好处是指令和可执行能力分离。SKILL.md负责告诉 AI“怎么做”scripts/负责真正执行docs/负责提供深层知识。AI 在运行 Skill 时可以根据任务需要调用不同的文件。4.3 Skill 的加载机制说明不同 AI 工具对 Skill 的目录约定不完全一样。比较常见的做法是把 Skill 目录放到项目下的.claude/skills/或类似的约定目录中主文件名固定为SKILL.md。例如cp -r web-test-skill .claude/skills/web-test-skill如果你的工具支持自定义 Skill 加载路径也可以配置到公共目录供多个项目复用。具体字段名和加载语法请以你正在使用的工具文档为准。本文重点是教你把 Skill 的内容搭起来工具差异不影响核心设计。5. 完整代码实现这一节是全文的重点。我会按文件逐个给出完整代码并解释关键逻辑。你可以直接复制改一改路径就能用。5.1 SKILL.md 主文件SKILL.md是整个 Skill 的核心。AI 面对测试任务时会通过这个文件了解你的测试规范。--- name: web-test-skill description: Web 自动化测试实战技能。适用于使用 Playwright 编写和执行 UI 自动化测试、定位页面元素、设计测试断言、生成 Markdown 测试报告的场景。当用户需要做 Web 端功能回归、冒烟测试、页面元素定位或测试用例设计时优先使用本 Skill。 allowed-tools: - Bash - Read - Write - Edit --- # Web 自动化测试 Skill ## 使用流程 1. 先确认被测页面 URL能本地访问就优先本地访问不要直接对没有授权的线上服务发起自动化请求。 2. 编写 Playwright 脚本时先明确要验证的业务场景再编写步骤。 3. 每条断言必须有明确的业务含义失败信息要包含期望值、实际值和定位信息。 4. 测试结束后生成 Markdown 报告说明总体结论和失败分析。 ## 定位策略优先级 从高到低依次选择 1. get_by_test_id 或 data-testid 2. get_by_role如按钮、链接、输入框 3. get_by_label / get_by_placeholder 4. CSS 选择器 5. XPath仅在以上方法都不满足时使用 ## 等待与稳定性要求 - 禁止直接使用 time.sleep(3) 等待元素这会降低脚本稳定性。 - 优先使用 wait_for_selector、wait_for_load_state、expect 等显式等待。 - 所有超时时间必须可配置默认超时为 10 秒。 ## 断言规范 - 断言内容必须对应业务规则而不是只判断元素存在。 - 失败信息必须包含期望值、实际值和定位信息。 - 不要把多个断言写在同一行。 - 断言失败时应保留当前页面截图作为排查依据。 ## 报告要求 - 输出格式为 Markdown。 - 报告头部包含测试时间、测试地址、执行环境。 - 每个检查项的状态必须是通过、失败、阻塞。 - 截图仅作为辅助证据最终结论以断言结果为准。 ## 脚本调用约定 - 执行冒烟测试时使用 python scripts/run_web_test.py。 - 生成测试用例时使用 python scripts/generate_test_case.py。 - 所有路径均相对于 Skill 根目录。关键点在于description要写得足够明确这样 AI 才能在多种任务中准确识别什么情况下应该加载这个 Skill。allowed-tools声明了 Skill 运行时允许使用的权限范围按照最小权限原则配置即可。5.2 自动化测试执行脚本 run_web_test.py这个脚本完成三件事访问被测页面、执行检查项、输出 Markdown 报告。# 文件路径web-test-skill/scripts/run_web_test.py import argparse import os import sys import time from datetime import datetime from playwright.sync_api import sync_playwright def build_report(url, results, screenshot_path): lines [ # Web 自动化测试报告, , f- 测试时间{datetime.now().strftime(%Y-%m-%d %H:%M:%S)}, f- 测试地址{url}, f- 截图文件{screenshot_path}, , ## 检查项结果, , | 检查项 | 结果 | 说明 |, | --- | --- | --- |, ] for item in results: status 通过 if item[ok] else 失败 lines.append(f| {item[name]} | {status} | {item[message]} |) return \n.join(lines) def main(): parser argparse.ArgumentParser(description基于 Playwright 的 Web 自动化测试脚本) parser.add_argument(--url, requiredTrue, help被测页面 URL) parser.add_argument(--selector, defaultbody, help核心元素选择器) parser.add_argument(--expected-title, default, help预期页面标题片段) parser.add_argument(--timeout, typeint, default10000, help元素等待超时时间单位毫秒) parser.add_argument(--output-dir, defaultreports, help报告输出目录) parser.add_argument(--headless, actionstore_true, help是否以无头模式运行) args parser.parse_args() os.makedirs(args.output_dir, exist_okTrue) results [] with sync_playwright() as p: browser p.chromium.launch(headlessargs.headless) page browser.new_page() # 检查点 1页面是否能成功访问 try: response page.goto(args.url, wait_untilload, timeoutargs.timeout) results.append({ name: 页面访问, ok: response is not None and response.ok, message: fHTTP {response.status} if response else 无响应, }) except Exception as exc: results.append({name: 页面访问, ok: False, message: str(exc)}) # 检查点 2页面标题是否符合预期 if args.expected_title: actual_title page.title() results.append({ name: 页面标题, ok: args.expected_title in actual_title, message: f期望包含「{args.expected_title}」实际为「{actual_title}」, }) # 检查点 3关键元素是否可见 try: page.wait_for_selector(args.selector, timeoutargs.timeout) results.append({ name: 关键元素, ok: True, message: f选择器 {args.selector} 已可见, }) except Exception as exc: results.append({name: 关键元素, ok: False, message: str(exc)}) screenshot_path os.path.join( args.output_dir, fscreenshot_{int(time.time())}.png ) page.screenshot(pathscreenshot_path) browser.close() report build_report(args.url, results, screenshot_path) report_path os.path.join(args.output_dir, report.md) with open(report_path, w, encodingutf-8) as f: f.write(report) print(report) failed [r for r in results if not r[ok]] sys.exit(1 if failed else 0) if __name__ __main__: main()脚本的核心逻辑有三个设计值得注意第一检查项被设计成列表每个检查项都有独立的成功/失败状态。这样即使一个检查项失败其他检查项也不会被跳过报告内容会更完整。第二所有等待都通过 Playwright 的wait_for_selector(timeoutargs.timeout)完成而不是time.sleep。这是 Web 自动化测试稳定性的关键。第三脚本结束时根据是否有失败项返回不同的退出码。这样把脚本接入 CI 流水线时可以直接用退出码判断测试是否通过。5.3 测试用例生成辅助脚本 generate_test_case.py除了执行冒烟测试Skill 还应该帮助 AI 快速生成结构化的测试用例文档。这个辅助脚本根据传入的步骤 JSON生成一个 Markdown 用例骨架。# 文件路径web-test-skill/scripts/generate_test_case.py import argparse import json from datetime import datetime from pathlib import Path TEMPLATE # 测试用例{case_name} ## 前置条件 - [ ] 被测环境已部署 - [ ] 测试数据已准备 ## 操作步骤 | 步骤 | 操作 | 预期结果 | 实际结果 | 是否通过 | | --- | --- | --- | --- | --- | {steps} ## 自动化脚本要点 python # TODO: 根据上述步骤使用本 Skill 的定位与断言规范编写 # 可参考 examples/ 下的示例。备注优先级{priority}创建时间{created_at} def main(): parser argparse.ArgumentParser(description生成测试用例 Markdown 骨架) parser.add_argument(--name, requiredTrue, help用例名称) parser.add_argument(--steps, help步骤 JSON 数组) parser.add_argument(--priority, defaultP2, help优先级 P0/P1/P2) args parser.parse_args()steps [] if args.steps: steps json.loads(args.steps) step_lines [] for idx, step in enumerate(steps, 1): op step.get(操作, ) expected step.get(预期, ) step_lines.append(f| {idx} | {op} | {expected} | | |) if not step_lines: step_lines.append(| 1 | 打开被测页面 | 页面正常加载 | | |) content TEMPLATE.format( case_nameargs.name, steps\n.join(step_lines), priorityargs.priority, created_atdatetime.now().strftime(%Y-%m-%d %H:%M:%S), ) out_path Path(fcases/{args.name}.md) out_path.parent.mkdir(exist_okTrue, parentsTrue) out_path.write_text(content, encodingutf-8) print(f用例已生成{out_path})ifname main: main()执行示例 bash python scripts/generate_test_case.py \ --name 登录成功用例 \ --steps [{操作:打开登录页,预期:页面加载完成},{操作:输入正确用户名和密码,预期:输入成功},{操作:点击登录按钮,预期:跳转到首页右上角显示用户名}] \ --priority P0这个脚本的意义在于它把“测试用例应该长什么样”固化了下来。AI 在编写用例时不再自由发挥格式而是按照这个骨架输出团队评审和后续统计都更方便。5.4 报告模板 report_template.md为了让 Skill 生成的报告风格统一再准备一个 Markdown 报告模板# {测试项目} 自动化测试报告 - 执行时间{time} - 执行人{owner} - 执行环境{env} ## 汇总 - 用例总数{total} - 通过数{passed} - 失败数{failed} - 通过率{pass_rate} ## 结果明细 {result_table} ## 失败分析 {failure_analysis} ## 结论 {conclusion}这个模板可以放在docs/report_template.md里。当 AI 需要生成完整测试报告时要求它严格按模板填充保证团队所有报告结构一致。5.5 依赖声明 requirements.txt在 Skill 根目录添加依赖文件# 文件路径web-test-skill/requirements.txt playwright1.40.0如果需要用 pytest 体系做更细粒度的用例管理可以再加pytest7.0.0 pytest-playwright0.4.0安装命令pip install -r requirements.txt5.6 示例文档 examples/smoke_test_demo.md为了增强 Skill 的引导能力可以在examples/下放一个冒烟测试示例AI 在生成新脚本时可以参考。# 冒烟测试示例本地测试页面 ## 目标 验证本地测试页面可以正常打开标题正确核心按钮可见。 ## 命令 bash python scripts/run_web_test.py \ --url http://127.0.0.1:8080/ \ --selector #submit-btn \ --expected-title 测试页面 \ --output-dir reports预期结果页面访问检查项通过页面标题检查项通过关键元素检查项通过把示例写进 Skill 目录相当于给 AI 一本“别人已经跑通的作业”它生成代码时的模仿成本会低很多。 ## 6. 运行结果与效果验证 ### 6.1 把 Skill 接入项目 先把 Skill 目录复制到 AI 工具的 Skill 加载目录以常见的 .claude/skills/ 约定为例 bash cp -r web-test-skill .claude/skills/web-test-skill然后确认目录结构find .claude/skills/web-test-skill -maxdepth 2 -type f正常输出应该包含.claude/skills/web-test-skill/SKILL.md .claude/skills/web-test-skill/requirements.txt .claude/skills/web-test-skill/scripts/run_web_test.py .claude/skills/web-test-skill/scripts/generate_test_case.py6.2 运行冒烟测试启动本地页面python -m http.server 8080执行 Skill 中的测试脚本python .claude/skills/web-test-skill/scripts/run_web_test.py \ --url http://127.0.0.1:8080/ \ --selector #submit-btn \ --expected-title 测试页面 \ --output-dir reports \ --headless预期输出类似# Web 自动化测试报告 - 测试时间2025-01-01 12:00:00 - 测试地址http://127.0.0.1:8080/ - 截图文件reports/screenshot_1704000000.png ## 检查项结果 | 检查项 | 结果 | 说明 | | --- | --- | --- | | 页面访问 | 通过 | HTTP 200 | | 页面标题 | 通过 | 期望包含「测试页面」实际为「测试页面」 | | 关键元素 | 通过 | 选择器 #submit-btn 已可见 |同时reports/report.md和截图文件会生成到本地。6.3 如何判断 Skill 生效判断 Skill 是否真正被 AI 加载可以从两个角度验证第一直接运行脚本确认脚本本身可用。这是最基础的验证。第二在 AI 对话中描述一个测试需求观察它是否引用了 Skill 中的规范。例如你问“用我们的测试规范写一个登录页检查”如果 AI 自动使用了get_by_role、wait_for_selector并主动要求生成 Markdown 报告说明 Skill 已经在起作用。如果 AI 完全没有反应大概率是 Skill 目录位置或描述信息没有配置正确。可以检查描述里是否包含了“Web 自动化测试”“Playwright”“测试报告”等触发词。7. 常见问题与排查思路实际落地时会遇到的问题往往不在代码本身而在环境、工具集成和稳定性上。下面列出高频问题。问题现象可能原因排查方式解决方案运行脚本报“Executable doesnt exist”未安装 Playwright 浏览器内核检查 Playwright 安装目录执行playwright install chromium打开页面超时本地服务端口不对或 URL 写错浏览器手动访问 URL 确认页面可打开检查--url确认服务已启动元素定位不到选择器过期或在 iframe / shadow DOM 中打开浏览器 DevTools 验证选择器能命中唯一元素改用>期望按钮文案为「提交订单」实际为「提交」。而不是locator not found8.5 使用 testid 作为首选定位方式如果项目还在开发阶段建议在关键交互元素上统一添加>
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门