@be-link/smart-test 1.0.1-beta.9 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,461 +1,524 @@
1
1
  # @be-link/smart-test
2
2
 
3
- AI-powered visual testing for Playwright | 基于 AI 视觉模型的 Playwright 测试工具
3
+ > AI-powered visual testing for Playwright - 基于 AI 视觉模型的 Playwright 测试工具
4
+
5
+ 使用 AI 视觉识别能力,让你的 E2E 测试更智能、更可靠。
4
6
 
5
7
  ## ✨ 特性
6
8
 
7
- - 🎯 **AI 视觉检查**:使用 AI 视觉模型自动检查页面截图是否符合预期
8
- - 🤖 **AI 代码生成**:使用 AI 自动生成测试用例和 Mock 数据
9
- - 📝 **TypeScript 支持**:完整的 TypeScript 类型定义
10
- - 🔧 **灵活配置**:支持自定义 AI 模型和服务地址
9
+ ### 🤖 AI 视觉检查
10
+
11
+ - 基于通义千问等视觉模型,智能检查页面是否符合预期
12
+ - 支持自然语言描述测试预期
13
+ - 自动识别页面问题并给出详细反馈
14
+
15
+ ### 🎯 零代码测试生成(开发中)
16
+
17
+ - **CLI 工具**:一条命令自动生成测试代码
18
+ - **录制模式**:访问页面自动录制接口和交互
19
+ - **代码分析**:扫描项目代码自动生成 Mock 数据
20
+ - **AI 生成**:基于自然语言描述生成完整测试
21
+
22
+ ### 🔧 灵活易用
23
+
24
+ - 与 Playwright 无缝集成,零侵入设计
25
+ - 支持全局配置和单次调用配置
26
+ - 优雅降级:无 API Key 时自动跳过
27
+ - 完整的 TypeScript 类型支持
28
+
29
+ ### 📸 自动化
30
+
31
+ - 自动截图并保存
32
+ - 自动生成 Mock 数据
33
+ - 自动生成测试用例
11
34
 
12
35
  ## 📦 安装
13
36
 
14
37
  ```bash
38
+ # 使用 pnpm(推荐)
15
39
  pnpm add -D @be-link/smart-test
40
+
41
+ # 使用 npm
42
+ npm install -D @be-link/smart-test
43
+
44
+ # 使用 yarn
45
+ yarn add -D @be-link/smart-test
16
46
  ```
17
47
 
18
48
  ## 🚀 快速开始
19
49
 
20
- ### 1. 配置 AI API
50
+ ### 方式一:使用 CLI 工具(推荐)⭐
21
51
 
22
- ```typescript
23
- import { configure } from '@be-link/smart-test';
52
+ #### 1. 初始化配置
24
53
 
25
- configure({
26
- apiKey: process.env.AI_API_KEY,
27
- baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
28
- visionModel: 'qwen3-vl-plus',
29
- codeModel: 'qwen3-coder-plus',
30
- });
54
+ ```bash
55
+ npx smart-test init
31
56
  ```
32
57
 
33
- ### 2. AI 视觉检查
58
+ 交互式配置向导会引导你完成设置:
34
59
 
35
- 在 Playwright 测试中使用 AI 检查页面截图:
60
+ ```
61
+ ━━━ 初始化 Smart Test 配置 ━━━
36
62
 
37
- ```typescript
38
- import { test } from '@playwright/test';
39
- import { aiReviewScreenshot } from '@be-link/smart-test';
63
+ ? 请输入 AI API Key: sk-xxxxx
64
+ ? 选择 AI 模型: 通义千问 (qwen3-vl-plus)
65
+ ? 测试文件目录: ./tests/e2e
66
+ ? Helpers 目录: ./tests/helpers
67
+ ? Playwright Base URL: http://localhost:8080
68
+ ? 文件命名风格: kebab-case
40
69
 
41
- test('页面显示正确', async ({ page }) => {
42
- await page.goto('/home');
70
+ 配置文件已创建: .smarttestrc.json
71
+ ```
43
72
 
44
- const result = await aiReviewScreenshot(page, '顶部显示logo和导航栏,主内容区域显示3个产品卡片');
73
+ #### 2. 生成测试代码(开发中)
45
74
 
46
- if (!result.skipped && result.issues?.length) {
47
- console.log('AI 发现的问题:', result.issues);
48
- }
49
- });
50
- ```
75
+ ```bash
76
+ # 录制模式 - 访问页面自动录制
77
+ npx smart-test record --url http://localhost:8080/coupon
51
78
 
52
- ### 3. AI 生成测试用例
79
+ # 代码分析模式 - 扫描页面代码
80
+ npx smart-test generate --page src/pages/coupon/index.tsx
53
81
 
54
- 自动生成完整的 Playwright 测试用例:
82
+ # 描述生成模式 - 基于自然语言
83
+ npx smart-test generate --desc "优惠券列表页,有可用券和已用券两个 tab"
55
84
 
56
- ```typescript
57
- import { aiGenerateTestCase } from '@be-link/smart-test';
58
-
59
- const result = await aiGenerateTestCase({
60
- pageUrl: '/coupon?userId=e2e-user&isPopup=true',
61
- scenario: '优惠券页面展示和 Tab 切换功能',
62
- apiMocks: [
63
- {
64
- path: '**/api/user/info/get-user-detail',
65
- description: '返回用户信息,包含 id、nickname、memberLevel 等字段',
66
- },
67
- {
68
- path: '**/api/user/coupon/get-available-coupons-grouped',
69
- description: '返回可用优惠券列表,按券 ID 分组',
70
- },
71
- ],
72
- aiCheckExpected: '顶部展示门店名称和用户昵称,列表中应显示3张优惠券卡片',
73
- testSteps: ['验证页面显示"优惠券"标题', '验证显示"夏日满减券"', '点击"核销券"按钮', '验证显示"到店核销券"文本'],
74
- });
85
+ # 交互式模式 - 引导式生成
86
+ npx smart-test generate --interactive
87
+ ```
75
88
 
76
- if (result.ok) {
77
- console.log('生成的测试代码:\n', result.code);
78
- }
89
+ #### 3. 运行测试
90
+
91
+ ```bash
92
+ npx playwright test
79
93
  ```
80
94
 
81
- ### 4. AI 生成 Mock 数据
95
+ ---
82
96
 
83
- 通过传入实际的 TypeScript 类型定义,AI 会生成完全符合接口规范的 Mock 数据:
97
+ ### 方式二:手动编程
84
98
 
85
- ```typescript
86
- import { aiGenerateMock } from '@be-link/smart-test';
87
- import fs from 'fs';
88
-
89
- // 读取类型定义文件
90
- const addressTypes = fs.readFileSync('./src/api/address/types.ts', 'utf-8');
91
-
92
- // 提取需要的类型定义
93
- const result = await aiGenerateMock({
94
- apiPath: '**/api/user/address/get-default-address',
95
- description: '返回用户默认地址信息',
96
- responseType: 'IDefaultAddressResp',
97
- typeDefinitions: [
98
- {
99
- typeName: 'IDefaultAddressResp',
100
- content: `export interface IDefaultAddressResp {
101
- /** 默认地址 */
102
- defaultAddress: IUserAddress | null;
103
- /** 自提地址 */
104
- pickupAddress: IPickUpStoreUserInfo | null;
105
- }`,
106
- },
107
- {
108
- typeName: 'IUserAddress',
109
- content: `export interface IUserAddress {
110
- /** 地址ID */
111
- id: string;
112
- /** 用户ID */
113
- userId: string;
114
- /** 收件人姓名 */
115
- receiverName: string;
116
- /** 收件人手机号 */
117
- receiverMobile: string;
118
- /** 省份名称 */
119
- provinceName: string;
120
- /** 城市名称 */
121
- cityName: string;
122
- /** 区县名称 */
123
- districtName: string;
124
- /** 详细地址 */
125
- detailAddress: string;
126
- /** 是否默认地址:1-是,0-否 */
127
- isDefault: number;
128
- /** 创建时间(毫秒时间戳) */
129
- createdAt: number;
130
- }`,
131
- },
132
- {
133
- typeName: 'IPickUpStoreUserInfo',
134
- content: `export interface IPickUpStoreUserInfo {
135
- id?: string;
136
- /** 用户ID */
137
- userId: string;
138
- /** 提货人手机号 */
139
- receiverMobile: string;
140
- /** 提货人名称 */
141
- receiverName: string;
142
- }`,
143
- },
144
- ],
145
- });
99
+ #### 1. 配置 API Key
146
100
 
147
- if (result.ok) {
148
- console.log('生成的 Mock 代码:\n', result.code);
149
- // AI 会严格按照类型定义生成符合规范的 mock 数据
150
- }
101
+ 在项目根目录创建 `.env` 文件:
102
+
103
+ ```bash
104
+ AI_API_KEY=sk-your-api-key-here
151
105
  ```
152
106
 
153
- ### 5. 通用代码生成
107
+ #### 2. 初始化配置
154
108
 
155
- 使用 AI 生成任意 TypeScript 代码:
109
+ `playwright.config.ts` 中配置:
156
110
 
157
111
  ```typescript
158
- import { aiGenerateCode } from '@be-link/smart-test';
159
-
160
- const result = await aiGenerateCode({
161
- prompt: '生成一个函数,用于计算两个日期之间的天数差',
162
- context: `// 项目中的日期工具示例
163
- function formatDate(date: Date): string {
164
- return date.toISOString().split('T')[0];
165
- }`,
112
+ import { defineConfig } from '@playwright/test';
113
+ import { configure } from '@be-link/smart-test';
114
+
115
+ // 初始化 AI 配置
116
+ configure({
117
+ apiKey: process.env.AI_API_KEY,
118
+ screenshotDir: './test-results/ai-screenshots',
166
119
  });
167
120
 
168
- if (result.ok) {
169
- console.log('生成的代码:\n', result.code);
170
- }
121
+ export default defineConfig({
122
+ // ... 其他 Playwright 配置
123
+ });
171
124
  ```
172
125
 
173
- ## 📖 API 文档
126
+ #### 3. 在测试中使用
174
127
 
175
- ### aiReviewScreenshot
128
+ ```typescript
129
+ import { test, expect } from '@playwright/test';
130
+ import { aiReviewScreenshot } from '@be-link/smart-test';
176
131
 
177
- 使用 AI 视觉模型检查页面截图是否符合预期。
132
+ test.describe('优惠券页面', () => {
133
+ test('AI 检查页面布局', async ({ page }) => {
134
+ await page.goto('/coupon');
178
135
 
179
- ```typescript
180
- function aiReviewScreenshot(page: Page, options: string | AiCheckOptions): Promise<AiCheckResult>;
136
+ // 使用 AI 检查页面
137
+ const result = await aiReviewScreenshot(page, '页面应该显示优惠券列表,包含标题、优惠券卡片和底部按钮');
138
+
139
+ // 处理结果
140
+ if (result.skipped) {
141
+ test.skip(); // 无 API Key 时跳过
142
+ }
143
+
144
+ expect(result.ok, result.issues?.join(', ')).toBeTruthy();
145
+ });
146
+ });
181
147
  ```
182
148
 
183
- **参数:**
149
+ ## 📖 CLI 命令参考
184
150
 
185
- - `page`: Playwright Page 对象
186
- - `options`: 检查选项
187
- - 字符串:直接传入预期描述
188
- - 对象:包含 `expected`(预期描述)、`fullPage`(是否全页截图)等配置
151
+ ### `smart-test init`
189
152
 
190
- **返回值:**
153
+ 初始化配置文件,交互式设置 AI API Key、模型、输出目录等。
191
154
 
192
- ```typescript
193
- interface AiCheckResult {
194
- ok: boolean; // 检查是否通过
195
- issues?: string[]; // 发现的问题列表
196
- suggestion?: string[]; // 改进建议列表
197
- skipped?: boolean; // 是否跳过检查
198
- reason?: string; // 跳过原因
199
- rawResponse?: string; // AI 原始响应
200
- }
155
+ ```bash
156
+ smart-test init
201
157
  ```
202
158
 
203
- ### aiGenerateTestCase
159
+ ### `smart-test generate` (开发中)
204
160
 
205
- 使用 AI 生成完整的 Playwright 测试用例。
161
+ 生成测试代码。
206
162
 
207
- ```typescript
208
- function aiGenerateTestCase(options: AiTestCaseGenerationOptions): Promise<AiCodeGenerationResult>;
209
- ```
163
+ ```bash
164
+ # 基础用法
165
+ smart-test generate
210
166
 
211
- **参数:**
167
+ # 指定页面(代码分析模式)
168
+ smart-test generate --page <path>
212
169
 
213
- ```typescript
214
- interface AiTestCaseGenerationOptions {
215
- pageUrl: string; // 页面 URL
216
- scenario: string; // 测试场景描述
217
- apiMocks?: ApiMockConfig[]; // API Mock 配置列表
218
- aiCheckExpected?: string; // AI 视觉检查预期
219
- testSteps?: string[]; // 测试步骤列表
220
- referenceCode?: string; // 参考代码
221
- // ... 以及 AiBaseConfig 的所有配置项
222
- }
170
+ # 指定 URL(录制模式)
171
+ smart-test generate --url <url>
223
172
 
224
- interface ApiMockConfig {
225
- path: string; // API 路径(支持通配符)
226
- description: string; // Mock 数据描述
227
- }
173
+ # 基于描述(自然语言模式)
174
+ smart-test generate --desc <description>
175
+
176
+ # 交互式模式
177
+ smart-test generate --interactive
178
+
179
+ # 指定输出目录
180
+ smart-test generate --page <path> --output tests/custom
181
+
182
+ # 预览模式(不写入文件)
183
+ smart-test generate --page <path> --dry-run
228
184
  ```
229
185
 
230
- ### aiGenerateMock
186
+ **选项:**
231
187
 
232
- 使用 AI 生成 API Mock 函数。
188
+ | 选项 | 简写 | 说明 |
189
+ | ---------------------- | ---- | ---------------------------- |
190
+ | `--page <path>` | `-p` | 页面文件路径(代码分析模式) |
191
+ | `--url <url>` | `-u` | 页面 URL(录制模式) |
192
+ | `--desc <description>` | `-d` | 页面描述(自然语言模式) |
193
+ | `--output <dir>` | `-o` | 输出目录 |
194
+ | `--interactive` | `-i` | 交互式模式 |
195
+ | `--dry-run` | | 预览模式,不写入文件 |
233
196
 
234
- ```typescript
235
- function aiGenerateMock(options: AiMockGenerationOptions): Promise<AiCodeGenerationResult>;
197
+ ### `smart-test record` (开发中)
198
+
199
+ 录制模式的快捷命令(`generate --url` 的别名)。
200
+
201
+ ```bash
202
+ # 基础录制
203
+ smart-test record --url http://localhost:8080/coupon
204
+
205
+ # 手动操作模式
206
+ smart-test record --url http://localhost:8080/coupon --manual
207
+
208
+ # 交互式引导
209
+ smart-test record --url http://localhost:8080/coupon --interactive
236
210
  ```
237
211
 
238
- **参数:**
212
+ **选项:**
239
213
 
240
- ```typescript
241
- interface AiMockGenerationOptions {
242
- apiPath: string; // API 路径
243
- description: string; // Mock 数据描述
244
- responseType?: string; // 响应数据类型名称(可选)
245
- typeDefinitions?: TypeDefinition[]; // TypeScript 类型定义列表(可选)
246
- referenceCode?: string; // 参考代码
247
- // ... 以及 AiBaseConfig 的所有配置项
248
- }
214
+ | 选项 | 简写 | 说明 |
215
+ | ---------------- | ---- | ------------------------ |
216
+ | `--url <url>` | `-u` | 要录制的页面 URL(必需) |
217
+ | `--output <dir>` | `-o` | 输出目录 |
218
+ | `--manual` | | 手动操作模式 |
219
+ | `--interactive` | | 交互式引导 |
249
220
 
250
- interface TypeDefinition {
251
- typeName: string; // 类型名称
252
- content: string; // 类型定义内容
253
- }
221
+ ### `smart-test config`
222
+
223
+ 查看当前配置。
224
+
225
+ ```bash
226
+ smart-test config
254
227
  ```
255
228
 
256
- **使用说明:**
257
- 传入 `typeDefinitions` 和 `responseType`,AI 会严格按照 TypeScript 类型定义生成 mock 数据,确保类型安全和数据准确性
229
+ ### 全局选项
230
+
231
+ | 选项 | 简写 | 说明 |
232
+ | ----------- | ---- | -------------------- |
233
+ | `--version` | `-V` | 显示版本号 |
234
+ | `--verbose` | `-v` | 详细输出(调试模式) |
235
+ | `--help` | `-h` | 显示帮助信息 |
236
+
237
+ ## 📖 编程 API 文档
258
238
 
259
- ### aiGenerateCode
239
+ ### `configure(config)`
260
240
 
261
- 通用的 AI 代码生成函数。
241
+ 配置全局设置。
262
242
 
263
243
  ```typescript
264
- function aiGenerateCode(options: AiCodeGenerationOptions): Promise<AiCodeGenerationResult>;
244
+ import { configure } from '@be-link/smart-test';
245
+
246
+ configure({
247
+ apiKey: 'sk-xxx', // AI API 密钥
248
+ baseURL: 'https://...', // AI 服务地址(可选)
249
+ model: 'qwen3-vl-plus', // AI 模型(可选)
250
+ timeout: 30000, // 超时时间(可选)
251
+ });
265
252
  ```
266
253
 
254
+ ### `aiReviewScreenshot(page, options)`
255
+
256
+ 使用 AI 检查页面截图。
257
+
267
258
  **参数:**
268
259
 
269
- ```typescript
270
- interface AiCodeGenerationOptions {
271
- prompt: string; // 代码生成描述
272
- context?: string; // 上下文代码
273
- // ... 以及 AiBaseConfig 的所有配置项
274
- }
275
- ```
260
+ - `page: Page` - Playwright Page 对象
261
+ - `options: string | AiCheckOptions` - 检查选项
276
262
 
277
- **返回值:**
263
+ **返回值:** `Promise<AiCheckResult>`
278
264
 
279
265
  ```typescript
280
- interface AiCodeGenerationResult {
281
- ok: boolean; // 是否成功生成
282
- code?: string; // 生成的代码
266
+ interface AiCheckResult {
267
+ ok: boolean; // 检查是否通过
268
+ issues?: string[]; // 问题列表
283
269
  skipped?: boolean; // 是否跳过
284
- reason?: string; // 跳过或失败原因
270
+ reason?: string; // 跳过原因
271
+ screenshotPath?: string; // 截图路径
285
272
  rawResponse?: string; // AI 原始响应
286
273
  }
287
274
  ```
288
275
 
289
- ### configure
276
+ ## 🎨 使用示例
290
277
 
291
- 配置全局 AI 设置。
278
+ ### 基础用法
292
279
 
293
280
  ```typescript
294
- function configure(config: Partial<AiBaseConfig>): void;
295
-
296
- interface AiBaseConfig {
297
- apiKey?: string; // AI API 密钥
298
- baseURL?: string; // AI 服务地址
299
- visionModel?: string; // 视觉模型名称
300
- codeModel?: string; // 代码模型名称
301
- timeout?: number; // 请求超时时间(毫秒)
302
- }
281
+ // 简单字符串描述
282
+ const result = await aiReviewScreenshot(page, '页面应该显示登录表单');
303
283
  ```
304
284
 
305
- ## 🎯 使用场景
285
+ ### 带配置的用法
306
286
 
307
- ### 场景 1:视觉回归测试
287
+ ```typescript
288
+ // 带配置对象
289
+ const result = await aiReviewScreenshot(page, {
290
+ expected: '页面应该显示商品列表',
291
+ model: 'gpt-4-vision-preview', // 使用其他模型
292
+ });
293
+ ```
308
294
 
309
- 使用 AI 自动检测页面的视觉变化,无需手动维护大量的断言代码:
295
+ ### 完整测试示例
310
296
 
311
297
  ```typescript
312
- test('首页显示正常', async ({ page }) => {
313
- await page.goto('/');
298
+ import { test, expect } from '@playwright/test';
299
+ import { aiReviewScreenshot } from '@be-link/smart-test';
314
300
 
315
- const result = await aiReviewScreenshot(page, {
316
- expected: '页面顶部显示网站logo和主导航,中间显示轮播图,下方显示4个产品分类卡片',
317
- fullPage: true,
301
+ test.describe('商品页面测试', () => {
302
+ test.beforeEach(async ({ page }) => {
303
+ await page.goto('/products');
304
+ await page.waitForLoadState('networkidle');
318
305
  });
319
306
 
320
- expect(result.ok).toBeTruthy();
321
- });
322
- ```
307
+ test('检查页面布局', async ({ page }) => {
308
+ const result = await aiReviewScreenshot(page, {
309
+ expected: '页面顶部应有搜索框,中间显示商品网格布局,底部有分页器',
310
+ fullPage: true,
311
+ });
323
312
 
324
- ### 场景 2:快速生成测试代码
313
+ if (result.skipped) {
314
+ console.log('跳过原因:', result.reason);
315
+ test.skip();
316
+ }
325
317
 
326
- 为新功能快速生成测试用例骨架,节省编写测试代码的时间:
318
+ if (!result.ok && result.issues) {
319
+ console.warn('发现的问题:', result.issues);
320
+ }
327
321
 
328
- ```typescript
329
- // 生成测试用例
330
- const result = await aiGenerateTestCase({
331
- pageUrl: '/product/123',
332
- scenario: '产品详情页展示和加入购物车功能',
333
- apiMocks: [
334
- { path: '**/api/product/detail', description: '返回产品详情' },
335
- { path: '**/api/cart/add', description: '加入购物车成功' },
336
- ],
337
- testSteps: ['验证显示产品名称和价格', '点击"加入购物车"按钮', '验证显示成功提示'],
338
- });
339
-
340
- // 将生成的代码保存到文件,然后根据实际需要调整
341
- ```
322
+ expect(result.ok, `AI 检查失败: ${result.issues?.join(', ')}`).toBeTruthy();
323
+ });
342
324
 
343
- ### 场景 3:Mock 数据管理
325
+ test('检查响应式布局', async ({ page }) => {
326
+ // 切换到移动端视图
327
+ await page.setViewportSize({ width: 375, height: 667 });
344
328
 
345
- 通过传入实际的类型定义,确保生成的 Mock 数据完全符合接口规范:
329
+ const result = await aiReviewScreenshot(page, '移动端布局:商品应该以单列显示,每个卡片占满宽度');
346
330
 
347
- ```typescript
348
- // 读取或定义类型
349
- import { readFileSync } from 'fs';
350
-
351
- const addressTypeContent = readFileSync('./src/api/address/types.ts', 'utf-8');
352
- // 或者直接定义类型字符串
353
-
354
- const result = await aiGenerateMock({
355
- apiPath: '**/api/user/address/get-default-address',
356
- description: '返回用户默认地址',
357
- responseType: 'IDefaultAddressResp',
358
- typeDefinitions: [
359
- {
360
- typeName: 'IDefaultAddressResp',
361
- content: extractTypeFromFile(addressTypeContent, 'IDefaultAddressResp'),
362
- },
363
- {
364
- typeName: 'IUserAddress',
365
- content: extractTypeFromFile(addressTypeContent, 'IUserAddress'),
366
- },
367
- ],
331
+ if (!result.skipped) {
332
+ expect(result.ok).toBeTruthy();
333
+ }
334
+ });
368
335
  });
369
-
370
- // 生成的 mock 数据会严格符合类型定义,包括:
371
- // - 字段类型匹配(string、number、boolean、null 等)
372
- // - 必填/可选字段正确
373
- // - 嵌套对象结构准确
374
- // - 根据注释生成合理的测试数据
375
336
  ```
376
337
 
377
- ## ⚙️ 配置说明
338
+ ## 🔧 配置文件
378
339
 
379
- ### 默认配置
340
+ ### `.smarttestrc.json`
380
341
 
381
- ```typescript
342
+ 使用 `smart-test init` 命令生成的配置文件:
343
+
344
+ ```json
382
345
  {
383
- baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
384
- visionModel: 'qwen3-vl-plus',
385
- codeModel: 'qwen3-coder-plus',
386
- timeout: 30000
346
+ "version": "1.0.0",
347
+ "ai": {
348
+ "model": "qwen3-vl-plus",
349
+ "apiKey": "${AI_API_KEY}",
350
+ "baseURL": "https://dashscope.aliyuncs.com/compatible-mode/v1",
351
+ "timeout": 30000
352
+ },
353
+ "output": {
354
+ "testsDir": "./tests/e2e",
355
+ "helpersDir": "./tests/helpers",
356
+ "naming": "kebab-case"
357
+ },
358
+ "templates": {
359
+ "mock": "default",
360
+ "test": "default"
361
+ },
362
+ "playwright": {
363
+ "baseURL": "http://localhost:8080",
364
+ "viewport": {
365
+ "width": 375,
366
+ "height": 667
367
+ },
368
+ "browser": "chromium"
369
+ }
387
370
  }
388
371
  ```
389
372
 
390
- ### 自定义配置
373
+ ### 支持的配置格式
374
+
375
+ - `.smarttestrc.json`
376
+ - `.smarttestrc.js`
377
+ - `smarttest.config.js`
378
+ - `package.json` 中的 `smarttest` 字段
391
379
 
392
- 可以在全局配置中设置默认值,也可以在每次调用时覆盖:
380
+ ## 🔧 高级配置
381
+
382
+ ### 支持多种 AI 模型
393
383
 
394
384
  ```typescript
395
- // 全局配置
385
+ // 使用通义千问(默认)
396
386
  configure({
397
- apiKey: process.env.AI_API_KEY,
398
- visionModel: 'custom-vision-model',
387
+ apiKey: process.env.QWEN_API_KEY,
388
+ baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
389
+ model: 'qwen3-vl-plus',
399
390
  });
400
391
 
401
- // 单次调用覆盖
402
- await aiReviewScreenshot(page, {
403
- expected: '...',
404
- visionModel: 'another-model', // 仅此次调用使用
392
+ // 使用 OpenAI GPT-4 Vision
393
+ configure({
394
+ apiKey: process.env.OPENAI_API_KEY,
395
+ baseURL: 'https://api.openai.com/v1',
396
+ model: 'gpt-4-vision-preview',
405
397
  });
406
398
  ```
407
399
 
408
- ## 🔍 最佳实践
400
+ ### 自定义截图存储
409
401
 
410
- ### 1. 环境变量管理
402
+ ```typescript
403
+ configure({
404
+ screenshotDir: './custom-screenshots',
405
+ saveScreenshots: true,
406
+ });
411
407
 
412
- 建议将 API Key 存储在环境变量中:
408
+ // 单次调用自定义
409
+ const result = await aiReviewScreenshot(page, {
410
+ expected: '...',
411
+ screenshotPrefix: 'my-feature',
412
+ screenshotDir: './feature-screenshots',
413
+ });
414
+ ```
413
415
 
414
- ```typescript
415
- // playwright.config.ts
416
- import { defineConfig } from '@playwright/test';
417
- import { configure } from '@be-link/smart-test';
416
+ ### 在 CI 环境中使用
418
417
 
418
+ ```typescript
419
+ // 在 CI 中可能不需要保存截图,减少存储开销
419
420
  configure({
420
421
  apiKey: process.env.AI_API_KEY,
421
- });
422
-
423
- export default defineConfig({
424
- // ... 其他配置
422
+ saveScreenshots: process.env.CI !== 'true',
425
423
  });
426
424
  ```
427
425
 
428
- ### 2. 合理使用 AI 检查
426
+ ## 🤔 常见问题
429
427
 
430
- AI 视觉检查适合用于:
428
+ ### Q: 没有配置 API Key 会怎样?
431
429
 
432
- - 整体布局和结构验证
433
- - ✅ 内容完整性检查
434
- - ✅ 视觉回归测试
430
+ A: 测试会自动跳过 AI 检查,返回 `skipped: true`,不会影响其他测试的执行。
435
431
 
436
- 不适合用于:
432
+ ### Q: 支持哪些 AI 模型?
437
433
 
438
- - 精确的像素级对比
439
- - ❌ 颜色值精确匹配
440
- - ❌ 性能敏感的场景
434
+ A: 理论上支持所有兼容 OpenAI Chat Completions API 的视觉模型,包括:
441
435
 
442
- ### 3. 组合使用
436
+ - 通义千问 (qwen3-vl-plus) - 默认
437
+ - OpenAI GPT-4 Vision
438
+ - 其他兼容的模型服务
443
439
 
444
- AI 检查与传统断言结合使用,获得最佳效果:
440
+ ### Q: CLI 生成的测试代码需要手动修改吗?
445
441
 
446
- ```typescript
447
- test('优惠券页面', async ({ page }) => {
448
- await page.goto('/coupon');
442
+ A: 生成的代码是可以直接运行的,但建议根据实际需求进行调整。AI 会尽量生成合理的测试用例,但可能无法覆盖所有业务场景。
449
443
 
450
- // 传统断言:精确的功能验证
451
- await expect(page.getByText('优惠券')).toBeVisible();
452
- await expect(page.getByRole('button', { name: '核销券' })).toBeVisible();
444
+ ### Q: 录制模式如何处理需要点击才能触发的接口?
453
445
 
454
- // AI 检查:整体视觉验证
455
- const aiResult = await aiReviewScreenshot(page, '页面整体布局合理,优惠券卡片排列整齐,信息展示清晰');
446
+ A: 录制模式支持三种方式:
456
447
 
457
- if (!aiResult.skipped && aiResult.issues?.length) {
458
- console.warn('AI 发现的潜在问题:', aiResult.issues);
459
- }
460
- });
448
+ 1. **手动操作**:`--manual` 参数,用户手动操作浏览器
449
+ 2. **交互式引导**:`--interactive` 参数,AI 引导用户操作
450
+ 3. **脚本引导**:`--actions` 参数,提供操作脚本自动执行
451
+
452
+ ### Q: 如何查看 AI 的原始响应?
453
+
454
+ A: 检查结果中的 `rawResponse` 字段包含了 AI 的原始响应内容。
455
+
456
+ ```typescript
457
+ const result = await aiReviewScreenshot(page, '...');
458
+ console.log('AI 原始响应:', result.rawResponse);
461
459
  ```
460
+
461
+ ### Q: 生成的代码文件如何组织?
462
+
463
+ A: 默认按页面分组:
464
+
465
+ - `tests/helpers/mock-{页面名}.ts` - Mock 数据
466
+ - `tests/e2e/{页面名}.spec.ts` - 测试用例
467
+
468
+ 可以通过 `--output` 参数自定义输出目录。
469
+
470
+ ## 🗺️ 开发路线图
471
+
472
+ ### ✅ 已完成
473
+
474
+ - [x] AI 视觉检查核心功能
475
+ - [x] CLI 基础架构
476
+ - [x] 配置系统
477
+ - [x] 交互式初始化
478
+
479
+ ### 🚧 开发中
480
+
481
+ - [ ] 录制模式(Phase 2)
482
+ - [ ] 网络请求录制
483
+ - [ ] HAR 文件解析
484
+ - [ ] AI 生成 Mock 代码
485
+ - [ ] 交互操作录制
486
+
487
+ ### 📅 计划中
488
+
489
+ - [ ] 代码分析模式(Phase 3)
490
+ - [ ] TypeScript AST 解析
491
+ - [ ] API 调用提取
492
+ - [ ] 类型定义分析
493
+
494
+ - [ ] 描述生成模式(Phase 4)
495
+ - [ ] 自然语言理解
496
+ - [ ] 交互式问答
497
+ - [ ] 代码生成
498
+
499
+ - [ ] 增强功能(Phase 5+)
500
+ - [ ] 增量更新
501
+ - [ ] 自定义模板
502
+ - [ ] 测试覆盖率分析
503
+ - [ ] VS Code 插件
504
+
505
+ ## 📄 文档
506
+
507
+ - [CLI 设计文档](./docs/CLI_DESIGN.md) - 完整的 CLI 工具设计方案
508
+ - [使用示例](./examples/) - 更多使用示例
509
+
510
+ ## 📝 License
511
+
512
+ MIT
513
+
514
+ ## 🤝 贡献
515
+
516
+ 欢迎提交 Issue 和 Pull Request!
517
+
518
+ ## 📮 联系方式
519
+
520
+ 如有问题,请在 [GitHub Issues](https://github.com/snowmountain-top/be-link/issues) 中提出。
521
+
522
+ ---
523
+
524
+ **版本**:v1.0.0 | **最后更新**:2025-12-30