前端自动化测试的 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 整体架构

复制代码
┌─────────────────────────────────────────────────────────────┐
│                     用户提供需求描述                          │
└────────────────────────┬────────────────────────────────────┘
                         ▼
┌─────────────────────────────────────────────────────────────┐
│  步骤一:测试需求分解(对应 Spec 的 Requirements)             │
│  输出:test-cases.md + automation-flow.md                    │
│  (AI 系统化生成测试用例,覆盖正向/反向/边界/异常场景)         │
└────────────────────────┬────────────────────────────────────┘
                         ▼
┌─────────────────────────────────────────────────────────────┐
│  步骤二:页面探测(对应 Spec 的 Design)                      │
│  输出:element-map.md + screenshots/ + execution-report.md   │
│  (Playwright 实际启动浏览器,探测真实选择器和接口响应)        │
└────────────────────────┬────────────────────────────────────┘
                         ▼
┌─────────────────────────────────────────────────────────────┐
│  步骤三:脚本生成(对应 Spec 的 Tasks)                       │
│  输出:xxx.spec.ts + fixtures/ + helpers/ + pages/           │
│  (选择器和断言值严格来源于步骤二的探测结果)                   │
└─────────────────────────────────────────────────────────────┘

3.2 关键设计决策

文档驱动,而非代码驱动:每个阶段的产出物都是结构化的 Markdown 文档。人类可读、可审查、可修改,阶段之间解耦,任何一步出错都可以单独重做。

选择器来源于真实探测,而非猜测:步骤二通过 Playwright 实际启动浏览器访问目标应用,探测并记录真实的页面元素选择器,同时记录备选选择器提高容错性。

接口响应优先的断言策略:前端 Toast 消息显示时间极短(2-5秒),自动化捕获不稳定。接口响应是确定性的、可靠的数据源,因此采用「接口响应拦截」作为第一优先级断言手段。

3.3 技术栈

组件 技术选型 说明
AI 编排引擎 Kiro Power 通过 Kiro Power 定义 AI Agent 的行为规范和技能编排
测试框架 Playwright 支持多浏览器、自动等待、网络拦截
脚本语言 TypeScript 类型安全,与 Playwright 原生集成
文档格式 Markdown 通用、可读、可版本控制

3.4 Kiro Power 技能编排

我们将工作流拆分为一个总控文件和三个技能文件:

复制代码
.kiro/steering/
├── 00-workflow-guide.md              # 总控文件(始终加载,提供全局上下文)
├── 01-test-requirement-analysis.md   # 步骤一:需求分解
├── 02-execute-automation-flow.md     # 步骤二:页面探测
└── 03-generate-playwright-scripts.md # 步骤三:脚本生成

总控文件始终加载,为 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)识别最优选择器,同时记录备选选择器。

typescript 复制代码
// 探测脚本核心逻辑示例
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):

markdown 复制代码
## 元素列表

### 元素 1: 用户名输入框
- 推荐选择器: `#username`
- 选择器类型: id
- 备选选择器: `input[placeholder="用户名:"]`
- 关联测试用例: TC-001, TC-002, TC-004, TC-005

### 元素 2: 登录按钮
- 推荐选择器: `button:has-text("登录")`
- 选择器类型: text
- 备选选择器: `button.ant-btn-primary`

## 接口响应记录

### 正确账号密码登录 (TC-001)
- 请求: POST /api/login
- 响应:
  {"code":"00000","msg":"success","success":true,"token":"xxx"}

### 错误密码登录 (TC-004)
- 请求: POST /api/login
- 响应:
  {"code":"500","msg":"用户名或者密码错误","success":false}

同时生成关键步骤的截图,便于人工审查。这些产出物就是 Spec 模式中的「设计文档」--- 基于真实探测结果,而非凭空猜测。

4.3 步骤三:脚本生成(Tasks)

基于步骤一的测试用例和步骤二的元素映射,AI 生成可直接运行的 Playwright 测试脚本:

typescript 复制代码
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('#rc-tabs-0-tab-account');
  });

  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/login') 
              && resp.request().method() === 'POST'
    );
    
    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('#pwd', loginData.validPassword);
    await page.click('button:has-text("登录")');
    
    // 前端表单校验,不发送接口请求
    const error = page.locator('.ant-form-item-explain-error');
    await expect(error).toContainText('用户名是必填项');
  });

  test('TC-004: 错误密码登录', async ({ page }) => {
    await page.fill('#username', loginData.validUser);
    await page.fill('#pwd', 'wrong_password');
    
    const responsePromise = page.waitForResponse(
      resp => resp.url().includes('/api/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);
  });
});

每一个选择器都可以追溯到 element-map.md,每一个断言值都可以追溯到实际拦截的接口响应。这就是 Spec 模式的力量 --- 实现严格遵循规格,不偏离设计意图。

4.4 微前端场景下的探测

在配置管理模块中,页面内容渲染在嵌套 iframe 中,探测脚本自动识别并适配:

复制代码
探测发现:
1. 页面内容渲染在嵌套 iframe 中
2. iframe 加载时间约 10-15 秒,需要轮询等待
3. 主页面与 iframe 内的 CSS 前缀不同,需分别处理
4. 表单字段通过 aria-label 定位最可靠
5. 弹出层(Drawer/Modal)渲染在 iframe 内部

AI 自动生成适配 iframe 的选择器策略:

typescript 复制代码
// iframe 内元素定位示例
const frame = page.frameLocator('iframe[name="content-frame"]');

// 使用 aria-label 定位表单字段
await frame.locator('[aria-label*="供应商"] .ant-select').click();
await frame.locator('[aria-label*="AppId"] input').fill('test-app-id');
await frame.locator('[aria-label*="AppKey"] input').fill('sk-test-key');

方案还内置了对 wujie(无界)微前端框架的自动检测:

typescript 复制代码
// wujie 微前端检测逻辑
const wujieResult = await page.evaluate(() => {
  const result = { isWujie: false, features: [] as string[] };
  
  // 检测 wujie 相关 DOM 元素
  const wujieElements = document.querySelectorAll(
    '[class*="wujie"], wujie-app, [data-wujie-id]'
  );
  if (wujieElements.length > 0) {
    result.isWujie = true;
  }
  
  // 检测 Shadow DOM 容器
  document.querySelectorAll('*').forEach(el => {
    if (el.shadowRoot && el.shadowRoot.querySelectorAll('*').length > 10) {
      result.isWujie = true;
    }
  });
  
  return result;
});

检测到 wujie 后,自动切换为 Shadow DOM 穿透选择器策略。

4.5 产出物总览

以登录模块为例,完整的产出物包括:

复制代码
test-docs/
├── requirement-overview.md          # 需求概述(6个功能模块)
├── execution-report.md              # 探测执行报告
├── _playwright-probe/
│   └── probe-login.ts               # 浏览器探测脚本
└── 登录/
    ├── test-cases.md                # 8个测试用例(P0-P2)
    ├── automation-flow.md           # 9个流程步骤(选择器已回填)
    ├── element-map.md               # 7个元素 + 3条接口响应
    └── screenshots/                 # 关键步骤截图

tests/
├── login.spec.ts                    # 可运行的测试脚本
├── fixtures/login.json              # 测试数据
├── helpers/auth.ts                  # 认证辅助函数
└── pages/login.page.ts             # Page Object 封装

五、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 驱动开发的理念应用到了前端自动化测试领域:

  1. 选择器零猜测 --- 所有选择器来源于 Playwright 对真实页面的探测结果
  2. 断言有据可依 --- 接口响应的断言期望值来源于实际拦截到的响应内容
  3. 全链路可追溯 --- 从需求描述到最终测试脚本,每一步都有对应的文档产出物
  4. 阶段解耦,灵活可控 --- 三个步骤独立执行,用户可在每个阶段检查和修正
  5. 低门槛、高效率 --- 测试人员只需提供需求描述,AI 负责全部技术实现

通过 Kiro Power,我们将自动化测试从「手工编码」提升到了「需求驱动的自动生成」,大幅降低了测试脚本的编写和维护成本。

相关推荐
YAwu112 小时前
HTML语义化渲染与CSS优先级机制的技术解析
前端
MgArcher2 小时前
Python高级特性:filter() 函数完全指南
前端·后端
一起学开源2 小时前
跨境电商多平台BI系统技术方案
ai·系统架构·技术方案
han_2 小时前
JavaScript设计模式(十):模板方法模式实现与应用
前端·javascript·设计模式
得物技术2 小时前
立正请站好:一个组件复用 Skill 的工程化实践|得物技术
前端·架构·ai编程
marsh02062 小时前
32 openclaw容器化部署:Docker与Kubernetes集成指南
docker·ai·容器·kubernetes·编程·技术
攀登的牵牛花2 小时前
OpenClaw 的内心独白,关于最近很火的Harness?
前端·openai
浩星2 小时前
electron系列8之Electron + Vue 3:构建现代化桌面应用(下)
前端·vue.js·electron
西西学代码2 小时前
查找设备页面(amap_map)
开发语言·前端·javascript