前端自动化测试的 Spec 模式:用 Kiro Power 实现从需求到脚本的全链路自动化
Spec 驱动开发的核心是:先定义「做什么」,再推导「怎么做」,最后验证「做对了没」。当我们把这套理念应用到前端自动化测试领域,会发生什么?本文介绍一种基于 Kiro Power 的自动化测试 Spec 模式,通过「三步式」工作流,将测试需求转化为可直接运行的 Playwright 脚本。
一、什么是自动化测试的 Spec 模式
如果你用过 Kiro 的 Spec 驱动开发,一定熟悉这个流程:Requirements → Design → Tasks。先明确需求规格,再做技术设计,最后拆解为可执行的任务。AI 负责执行,人负责审查。
我们把同样的理念搬到了前端自动化测试:
| Spec 驱动开发 | 自动化测试 Spec 模式 | 对应关系 |
|---|---|---|
| Requirements(需求文档) | test-cases.md(测试用例) | 先定义「测什么」 |
| Design(技术设计) | element-map.md(元素映射) | 基于真实探测确定「怎么测」 |
| Tasks(实现任务) | xxx.spec.ts(测试脚本) | 严格遵循规格生成代码 |
这不是简单的类比。两者共享同一套核心优势:
- 需求先行,实现后置 — 先系统化生成测试用例,确保覆盖完备,再考虑技术实现
- 规格即资产 — 中间产物不是临时文件,而是长期有效的、可审查可复用的测试资产
- 阶段解耦 — 需求变了改用例,页面改了更新元素映射,脚本风格要调整就重新生成,互不影响
- AI 执行,人审查 — AI 负责全部技术工作,人只需在每个阶段确认输出是否符合预期
- 全链路可追溯 — 从原始需求到最终脚本,每一步都有文档记录,任何断言值都可追溯到真实接口响应
二、传统自动化测试的痛点
在展开方案细节之前,先看看传统做法为什么不够好:
| 痛点 | 描述 |
|---|---|
| 选择器不稳定 | 凭经验猜测 CSS 选择器,页面一改就失效 |
| 断言不可靠 | 期望值靠人工推测,与实际接口响应不一致 |
| 维护成本高 | 需求变更后需手动逐一修改脚本 |
| 知识断层 | 测试用例、元素信息、脚本之间缺乏关联,难以追溯 |
| 微前端适配难 | wujie / qiankun 等微前端框架下,Shadow DOM 穿透选择器编写复杂 |
传统做法是:测试人员手动打开浏览器 DevTools → 逐个复制选择器 → 编写测试脚本 → 反复调试。一个中等复杂度的模块,往往需要数小时才能完成。
根本原因在于:传统方式是「代码驱动」的,直接从需求跳到脚本编写,中间缺少结构化的规格定义环节。而 Spec 模式通过引入文档化的中间层,让每一步都有据可依。
三、三步式 Spec 工作流
3.1 整体架构

3.2 关键设计决策
文档驱动,而非代码驱动:每个阶段的产出物都是结构化的 Markdown 文档。人类可读、可审查、可修改,阶段之间解耦,任何一步出错都可以单独重做。
选择器来源于真实探测,而非猜测:步骤二通过 Playwright 实际启动浏览器访问目标应用,探测并记录真实的页面元素选择器,同时记录备选选择器提高容错性。
接口响应优先的断言策略:前端 Toast 消息显示时间极短(2-5秒),自动化捕获不稳定。接口响应是确定性的、可靠的数据源,因此采用「接口响应拦截」作为第一优先级断言手段。
3.3 技术栈
| 组件 | 技术选型 | 说明 |
|---|---|---|
| AI 编排引擎 | Kiro Power | 通过 Kiro Power 定义 AI Agent 的行为规范和技能编排 |
| 测试框架 | Playwright | 支持多浏览器、自动等待、网络拦截 |
| 脚本语言 | TypeScript | 类型安全,与 Playwright 原生集成 |
| 文档格式 | Markdown | 通用、可读、可版本控制 |
3.4 Kiro Power 技能编排
我们将工作流拆分为一个总控文件和三个技能文件:

总控文件始终加载,为 AI 提供全局上下文。步骤技能文件按需通过 # 引用激活,避免上下文污染。环境初始化技能在首次使用或依赖缺失时自动触发。
四、Demo 演示:以「配置管理系统」为例
我们以一个典型的企业级配置管理系统为例,演示完整的 Spec 工作流。该系统包含以下功能模块:

4.1 步骤一:需求分解(Requirements)
用户只需提供简单的需求描述:
登录功能:选择账号密码登录、输入用户名和密码
导航至配置页面
添加配置:选择供应商、填写 AppId、AppKey、BaseUrl
查询:输入 AppId 进行筛选
编辑:修改供应商、AppId、AppKey、BaseUrl
删除配置
AI 自动将需求拆分为 6 个功能模块,为每个模块生成标准化的测试用例文档。以登录模块为例,AI 生成了 8 个测试用例,覆盖 P0-P2 优先级:
| 用例编号 | 场景 | 优先级 | 类型 |
|---|---|---|---|
| TC-001 | 正确账号密码登录 | P0 | 正向 |
| TC-002 | 用户名为空登录 | P1 | 反向 |
| TC-003 | 密码为空登录 | P1 | 反向 |
| TC-004 | 错误密码登录 | P0 | 反向 |
| TC-005 | 不存在的用户名登录 | P1 | 反向 |
| TC-006 | 密码含特殊字符登录 | P2 | 边界 |
| TC-007 | 超长用户名登录 | P2 | 边界 |
| TC-008 | 连续多次错误密码登录 | P1 | 异常 |
同时生成自动化流程文档(automation-flow.md),预留选择器字段待步骤二填充。这就是 Spec 模式中「先定义规格」的体现 — 在动手写任何代码之前,先把「测什么、怎么测」想清楚。
4.2 步骤二:页面探测(Design)
这是整个方案最核心的环节,也是 Spec 模式中「基于事实做设计」的体现。AI 生成 Playwright 探测脚本,实际启动浏览器访问目标应用,自动完成以下工作:
元素选择器识别:按优先级策略(data-testid > id > aria-label > name > placeholder > text > css)识别最优选择器,同时记录备选选择器。
// 探测脚本核心逻辑示例
async function probe() {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
// 访问目标页面
await page.goto(TARGET_URL, { waitUntil: 'networkidle' });
// 自动识别页面元素
const inputs = await page.evaluate(() => {
const result: any[] = [];
document.querySelectorAll('input').forEach(el => {
const rect = el.getBoundingClientRect();
if (rect.width > 0 && rect.height > 0) {
result.push({
id: el.id,
name: (el as HTMLInputElement).name,
type: (el as HTMLInputElement).type,
placeholder: (el as HTMLInputElement).placeholder,
});
}
});
return result;
});
// 注册接口响应监听
const responsePromise = page.waitForResponse(
resp => resp.url().includes('/api/login')
&& resp.request().method() === 'POST',
{ timeout: 15000 }
);
// 执行操作并捕获接口响应
await page.click('button:has-text("登录")');
const response = await responsePromise;
const body = await response.json();
// 记录接口响应用于后续断言
console.log('接口响应:', JSON.stringify(body));
}
接口响应拦截:自动拦截关键接口的请求和响应,记录实际返回内容作为断言依据。
探测完成后,生成结构化的元素映射文档(element-map.md):
## 元素列表
### 元素 1: 账户密码登录切换标签
- 推荐选择器: `.rootAnt-tabs-tab-btn:has-text("账户密码登录")`
- 选择器类型: css+text
- 备选选择器: `text=账户密码登录`
- 特殊说明: 默认激活的是"域控登录"标签,需要先点击切换
### 元素 2: 用户名输入框
- 推荐选择器: `#username`
- 选择器类型: id
- 备选选择器: `input[placeholder="用户名:"]`
- 关联测试用例: TC-001, TC-002, TC-003
### 元素 3: 登录按钮
- 推荐选择器: `button:has-text("登 录")`
- 选择器类型: css+text
- 备选选择器: `.rootAnt-btn-primary.rootAnt-btn-lg`
- 特殊说明: 按钮文本有空格:"登 录"(Ant Design 特征)
## 接口响应记录
### 账号密码正常登录 (TC-001)
- 请求: POST /api/user/login
- 响应:
{"code":"00000","msg":"success","success":true,"token":"eyJhbGciOiJIUzI1NiJ9..."}
### 密码错误登录失败 (TC-002)
- 请求: POST /api/user/login
- 响应:
{"code":"500","msg":"用户名或者密码错误","success":false}
同时生成关键步骤的截图,便于人工审查。这些产出物就是 Spec 模式中的「设计文档」— 基于真实探测结果,而非凭空猜测。
4.3 步骤三:脚本生成(Tasks)
基于步骤一的测试用例和步骤二的元素映射,AI 生成可直接运行的 Playwright 测试脚本:
import { test, expect } from '@playwright/test';
import loginData from './fixtures/login.json';
test.describe('登录功能', () => {
test.beforeEach(async ({ page }) => {
await page.goto(loginData.baseUrl);
// 切换到账号密码登录 Tab(默认激活的是"域控登录")
await page.click('.rootAnt-tabs-tab-btn:has-text("账户密码登录")');
});
test('TC-001: 账号密码正常登录', async ({ page }) => {
await page.fill('#username', loginData.validUser);
await page.fill('#pwd', loginData.validPassword);
// 监听登录接口响应
const responsePromise = page.waitForResponse(
resp => resp.url().includes('/api/user/login')
&& resp.request().method() === 'POST'
);
// 注意:按钮文本有空格"登 录"(Ant Design 特征)
await page.click('button:has-text("登 录")');
const response = await responsePromise;
const body = await response.json();
// 断言值来源于 element-map.md 中记录的实际接口响应
expect(body.code).toBe('00000');
expect(body.success).toBe(true);
expect(body.token).toBeTruthy();
});
test('TC-002: 密码错误登录失败', async ({ page }) => {
await page.fill('#username', loginData.validUser);
await page.fill('#pwd', 'wrong_password');
const responsePromise = page.waitForResponse(
resp => resp.url().includes('/api/user/login')
&& resp.request().method() === 'POST'
);
await page.click('button:has-text("登 录")');
const response = await responsePromise;
const body = await response.json();
// 断言值来源于实际拦截的接口响应
expect(body.code).toBe('500');
expect(body.msg).toBe('用户名或者密码错误');
expect(body.success).toBe(false);
});
test('TC-003: 用户名为空登录', async ({ page }) => {
await page.fill('#pwd', loginData.validPassword);
await page.click('button:has-text("登 录")');
// 前端表单校验,不发送接口请求
const error = page.locator('.rootAnt-form-item-explain-error');
await expect(error).toContainText('用户名是必填项');
});
});
每一个选择器都可以追溯到 element-map.md,每一个断言值都可以追溯到实际拦截的接口响应。这就是 Spec 模式的力量 — 实现严格遵循规格,不偏离设计意图。
4.4 微前端场景下的探测
在 供应商配置管理模块中,页面架构为 wujie 微前端 + NocoBase 低代码平台。探测脚本自动识别页面架构并选择最优策略:
页面架构探测结果:
- 主应用: Ant Design Pro(CSS 前缀: rootAnt-)
- 功能页面: wujie 微前端 + NocoBase(CSS 前缀: ant-)
- iframe 直接访问 URL: /nocobase/admin/xxx?embed=true
- 直接访问验证: 通过(916 个元素,页面完整加载)
- 表单引擎: NocoBase 内置表单
- 数据集合名: app_config
方案内置了三种页面架构的自动检测和适配策略:
策略 A:iframe 直接访问模式(本 Demo 采用)
登录主应用获取认证 Cookie 后,直接访问 iframe 的 src 地址,绕过 wujie 微前端嵌套,使 page.locator() 正常工作:
// 登录主应用后,直接访问 NocoBase 页面
await page.goto('https://example.com/nocobase/admin/xxx?embed=true');
await page.waitForLoadState('networkidle');
// NocoBase 元素通过 aria-label 定位(无 id/name 属性)
await page.locator('[aria-label="action-Action-添加-create-app_config-table"]').click();
await page.locator('[aria-label*="app_config.app_id-AppId"] .ant-input').fill('test');
策略 B:wujie 微前端模式
当 iframe 直接访问不可用时,使用 Shadow DOM 穿透策略。
策略 C:普通页面模式
直接使用标准 Playwright API,无特殊处理。
4.5 产出物总览
完整的产出物目录结构如下:
test-docs/
├── requirement-overview.md # 需求概述(3个功能模块)
├── architecture-info.md # 页面架构探测结果
├── menu-url-map.md # 菜单导航地址映射
├── execution-report.md # 探测执行报告
├── _playwright-probe/ # 浏览器探测脚本
│ ├── probe-architecture.ts
│ ├── probe-login-elements.ts
│ ├── probe-login-flow.ts
│ ├── probe-config-page.ts
│ └── probe-config-crud.ts
├── login/ # 登录模块
│ ├── test-cases.md # 3个测试用例
│ ├── automation-flow.md # 流程步骤(选择器已回填)
│ └── element-map.md # 5个元素 + 接口响应
├── navigation/ # 导航模块
│ ├── test-cases.md
│ ├── automation-flow.md
│ └── element-map.md
└── vendor-config/ # 供应商配置管理模块
├── test-cases.md # 7个测试用例(TC-007~TC-013)
├── automation-flow.md
└── element-map.md # 18个元素 + 接口响应
tests/
├── login.spec.ts # 登录测试脚本
├── vendor-config.spec.ts # 供应商配置管理测试脚本
├── fixtures/
│ └── login.json # 测试数据
└── helpers/
└── auth.ts # 认证辅助函数
五、Spec 模式 vs 传统方式
| 维度 | 传统手工编写 | Spec 模式(AI 驱动) |
|---|---|---|
| 选择器来源 | 手动查看 DOM 并编写 | AI 实际启动浏览器探测,自动识别最优选择器 |
| 断言依据 | 凭经验猜测预期值 | 基于实际拦截的接口响应数据 |
| 用例覆盖度 | 依赖个人经验,容易遗漏 | AI 系统化生成,覆盖正向/反向/边界/异常 |
| 编写效率 | 一个模块通常需要数小时 | 三步流程,分钟级完成 |
| 可维护性 | 脚本与需求脱节 | 文档驱动,需求→用例→脚本全链路可追溯 |
| 微前端适配 | 需深入了解框架原理 | 自动检测并切换 Shadow DOM 穿透策略 |
| 知识沉淀 | 知识在个人脑中 | 结构化文档沉淀,团队可共享 |
六、适用场景
企业级 Web 应用的 E2E 测试:尤其是使用 Ant Design、Element UI 等组件库的中后台系统,AI 对这些组件的选择器模式有很好的识别能力。
微前端架构的复杂应用:wujie、qiankun 等微前端框架下,Shadow DOM 穿透选择器的编写是一个高门槛工作,AI 可以自动检测并适配。
快速建立自动化测试体系:对于还没有自动化测试的项目,这套方案可以在极短时间内建立起覆盖核心功能的测试用例集。
需求频繁变更的敏捷项目:Spec 模式的阶段解耦特性,使得页面改版只需重新执行步骤二更新选择器,无需从头编写脚本。
测试团队技能提升:降低 Playwright 脚本编写门槛,测试人员只需提供需求描述,AI 负责全部技术实现。
七、总结
这套方案的本质,是把 Spec 驱动开发的理念应用到了前端自动化测试领域:
- 选择器零猜测 — 所有选择器来源于 Playwright 对真实页面的探测结果
- 断言有据可依 — 接口响应的断言期望值来源于实际拦截到的响应内容
- 全链路可追溯 — 从需求描述到最终测试脚本,每一步都有对应的文档产出物
- 阶段解耦,灵活可控 — 三个步骤独立执行,用户可在每个阶段检查和修正
- 低门槛、高效率 — 测试人员只需提供需求描述,AI 负责全部技术实现
通过 Kiro Power,我们将自动化测试从「手工编码」提升到了「需求驱动的自动生成」,大幅降低了测试脚本的编写和维护成本。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)