Skip to content

Commit 1b92105

Browse files
committed
feat: 平台识别规则+空项目处理+UI对比度修复+代码先行零章
1 parent 9050078 commit 1b92105

8 files changed

Lines changed: 214 additions & 18 deletions

File tree

AGENTS.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,46 @@
55
66
---
77

8+
## 零、平台识别规则(写蓝本前必须先确定 platform)
9+
10+
**在 platform 确定之前,禁止生成任何蓝本内容。** 错误的 platform 会导致规则、选择器、动作全部用错,整个蓝本无法运行。
11+
12+
### 识别顺序(按优先级从高到低)
13+
14+
1. **检查已有蓝本** — 读 `testpilot/*.json`,看 `platform` 字段;**但必须与代码特征核对(见下表)**,若明显矛盾则以代码为准并纠正
15+
2. **检查代码文件特征**(唯一客观依据):
16+
17+
| 文件/特征 | platform |
18+
|-----------|----------|
19+
| `pubspec.yaml` / `AndroidManifest.xml` / `*.kt` / `*.java` | `android` |
20+
| `*.xcodeproj` / `*.swift` / `Info.plist` | `ios` |
21+
| `app.json` + `pages/` 目录(小程序结构) | `miniprogram` |
22+
| `*.xaml` / `*.wxs` / `tkinter` / `pywinauto` / Electron + `BrowserWindow` | `desktop` |
23+
| `package.json` + `*.html` / React / Vue / Angular / 纯HTML | `web` |
24+
25+
3. **`testpilot/CHANGELOG.md`**(如存在)— 里面可能已注明平台
26+
4. **以上都无法确定 → 停下来,明确问用户**:「这个项目是 Web / Android / iOS / 小程序 / 桌面应用 中的哪一种?」
27+
28+
### 发现平台写错了,如何纠正
29+
30+
- 发现已有蓝本的 `platform` 与代码特征矛盾 → **立即停止**,告知用户「检测到蓝本 platform 字段为 xxx,但项目代码特征显示应为 yyy,已自动修正」
31+
- 修正步骤:① 更新所有蓝本的 `platform` 字段 ② 重读正确平台规则文件 ③ 检查选择器/动作是否需要同步修改
32+
- **不要沉默地继续写错误的蓝本**
33+
34+
### 空项目或无法判断时的处理规则
35+
36+
1. **项目完全为空**(无任何源码文件)→ **不写蓝本,静默等待**。空项目没有可测功能,无需操作,也不要打扰用户。
37+
2. **代码特征模糊**(如只有 README、配置文件,看不出平台)→ 同上,继续等待直到出现明确的代码文件。
38+
3. **用户描述与代码矛盾** → 以代码为准。用户说"这是 Android 项目"但目录里只有 `index.html` → 判断为 web,告知用户。
39+
40+
**已生成错误蓝本后如何纠正:**
41+
1. 你发现代码特征与蓝本 `platform` 矛盾(如蓝本写 `"platform": "web"` 但项目有 `AndroidManifest.xml`
42+
2. **主动告知用户**:「检测到蓝本 platform=web,但项目代码显示应为 android,正在自动修正」
43+
3. 自动执行:修改所有蓝本的 `platform` 字段 → 重读 `.testpilot/platforms/android.md` → 检查所有选择器和动作是否符合 android 规范 → 修正不符规范的部分
44+
4. **不需要等用户确认,直接修正并告知结果**
45+
46+
---
47+
848
## 一、蓝本自动生成(最重要)
949

1050
当项目中**不存在** `testpilot.json``testpilot/` 目录时,你在完成功能开发后**必须**自动生成蓝本文件。

extension/src/rulesInjector.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ function detectAllIDEs(): string[] {
8181
* 模板版本号。每次更新模板内容时递增。
8282
* rulesInjector 会检测已注入文件的版本号,低于此版本则自动更新。
8383
*/
84-
const TEMPLATE_VERSION = 2;
84+
const TEMPLATE_VERSION = 5;
8585

8686
/** 从文件内容中提取版本号,找不到返回 0(旧版无版本标记) */
8787
function extractVersion(content: string): number {
@@ -115,6 +115,41 @@ function getTemplateContent(): string {
115115
116116
---
117117
118+
## 零(前)、平台识别规则(写蓝本前必须先确定 platform)
119+
120+
**在 platform 确定之前,禁止生成任何蓝本内容。**
121+
122+
### 识别顺序(按优先级)
123+
124+
1. **检查代码文件特征**(唯一客观依据):
125+
126+
| 文件/特征 | platform |
127+
|-----------|----------|
128+
| \`pubspec.yaml\` / \`AndroidManifest.xml\` / \`*.kt\` / \`*.java\` | \`android\` |
129+
| \`*.xcodeproj\` / \`*.swift\` / \`Info.plist\` | \`ios\` |
130+
| \`app.json\` + \`pages/\` 目录(小程序结构) | \`miniprogram\` |
131+
| \`*.xaml\` / \`tkinter\` / \`pywinauto\` / Electron + \`BrowserWindow\` | \`desktop\` |
132+
| \`package.json\` + \`*.html\` / React / Vue / Angular | \`web\` |
133+
134+
2. **检查已有蓝本的 platform 字段** — 但必须与代码特征核对,若矛盾以代码为准
135+
3. **读 \`testpilot/CHANGELOG.md\`**(如存在)— 里面可能已注明平台
136+
4. **以上都无法确定 → 停下来问用户**:「这是 Web / Android / iOS / 小程序 / 桌面 中的哪种?」
137+
138+
### 空项目或无法判断时的处理规则
139+
140+
- **项目完全为空**(无源码)→ **不写蓝本,静默等待**,不要打扰用户
141+
- **代码特征模糊** → 同上,等待出现明确代码文件
142+
- **用户描述与代码矛盾** → 以代码为准,告知用户
143+
144+
### 发现平台写错时如何纠正
145+
146+
1. 发现代码特征与蓝本 \`platform\` 矛盾(如蓝本写 \`"web"\` 但项目有 \`AndroidManifest.xml\`)
147+
2. **主动告知**:「检测到蓝本 platform=web,但项目代码显示应为 android,正在自动修正」
148+
3. 自动执行:更新所有蓝本 \`platform\` → 重读 \`.testpilot/platforms/android.md\` → 修正不符规范的选择器和动作
149+
4. **不需要等用户确认,直接修正并告知结果**
150+
151+
---
152+
118153
## 零、蓝本语言规则
119154
120155
蓝本中的 \`name\`、\`description\`、\`expected\`、\`app_name\` 等文字内容**必须使用用户项目的语言**:

extension/src/sidebarProvider.ts

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,36 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
523523
}
524524

525525
private async _handleCopyBlueprintPrompt(platform: string, projectDir: string = ""): Promise<void> {
526+
const platformNames: Record<string, string> = {
527+
web: "Web",
528+
miniprogram: "微信小程序",
529+
android: "Android/Flutter",
530+
desktop: "Windows桌面",
531+
ios: "iOS/SwiftUI",
532+
};
533+
const pName = platformNames[platform] || "Web";
534+
535+
const lines: string[] = [];
536+
if (projectDir) {
537+
lines.push(`当前项目路径:${projectDir.replace(/\\/g, "/")}`);
538+
lines.push(`请直接读取该目录下的源代码生成蓝本,无需再次询问项目路径。`);
539+
lines.push(``);
540+
}
541+
lines.push(`请为当前【${pName}】项目生成测试蓝本。`);
542+
lines.push(``);
543+
lines.push(`⚠️ 生成前请先按顺序完成以下步骤(缺一不可):`);
544+
lines.push(`1. 阅读 AGENTS.md(蓝本通用规则)`);
545+
lines.push(`2. 阅读 .testpilot/platforms/${platform}.md(${pName}平台专属规则、选择器规范和完整模板)`);
546+
lines.push(`3. 通读项目源代码,确认已实现的功能列表`);
547+
lines.push(`4. 按规则要求生成完整蓝本,保存到 testpilot/ 目录`);
548+
549+
const prompt = lines.join("\n");
550+
await vscode.env.clipboard.writeText(prompt);
551+
vscode.window.showInformationMessage(`✅ ${pName}蓝本提示词已复制!请粘贴给编程AI,它会先读规则文件再生成蓝本。`);
552+
}
553+
554+
// ── 以下为旧版长提示词备份(已废弃,改用短口令模式) ──
555+
private async _handleCopyBlueprintPrompt_LEGACY(platform: string, projectDir: string = ""): Promise<void> {
526556
const commonRules = `══════ 测试设计黄金规则(必须严格遵守) ══════
527557
528558
【铁律0:每个项目必须有独立蓝本】
@@ -1119,18 +1149,19 @@ ${commonRules}`;
11191149
<title>TestPilot AI</title>
11201150
<style>
11211151
:root {
1122-
--bg: var(--vscode-sideBar-background);
1123-
--fg: var(--vscode-sideBar-foreground);
1124-
--input-bg: var(--vscode-input-background);
1125-
--input-border: var(--vscode-input-border);
1126-
--input-fg: var(--vscode-input-foreground);
1127-
--btn-bg: var(--vscode-button-background);
1128-
--btn-fg: var(--vscode-button-foreground);
1129-
--btn-hover: var(--vscode-button-hoverBackground);
1152+
--bg: var(--vscode-sideBar-background, #1e1e1e);
1153+
--fg: var(--vscode-sideBar-foreground, #cccccc);
1154+
--input-bg: var(--vscode-input-background, #3c3c3c);
1155+
--input-border: var(--vscode-input-border, rgba(255,255,255,0.35));
1156+
--input-fg: var(--vscode-input-foreground, #cccccc);
1157+
--btn-bg: var(--vscode-button-background, #0e639c);
1158+
--btn-fg: var(--vscode-button-foreground, #ffffff);
1159+
--btn-hover: var(--vscode-button-hoverBackground, #1177bb);
1160+
--muted: var(--vscode-descriptionForeground, rgba(204,204,204,0.55));
11301161
--success: #4ec9b0;
11311162
--error: #f44747;
11321163
--warn: #cca700;
1133-
--info: var(--vscode-descriptionForeground);
1164+
--info: var(--vscode-descriptionForeground, #9d9d9d);
11341165
}
11351166
* { margin: 0; padding: 0; box-sizing: border-box; }
11361167
body { font-family: var(--vscode-font-family); font-size: 13px; color: var(--fg); padding: 12px; }
@@ -1155,11 +1186,12 @@ ${commonRules}`;
11551186
button {
11561187
width: 100%; padding: 7px; margin-top: 8px; font-size: 13px; font-weight: 600;
11571188
background: var(--btn-bg); color: var(--btn-fg);
1158-
border: none; border-radius: 3px; cursor: pointer;
1189+
border: 1px solid rgba(255,255,255,0.55); border-radius: 3px; cursor: pointer;
11591190
}
1160-
button:hover { background: var(--btn-hover); }
1191+
button:hover { background: var(--btn-hover); border-color: rgba(255,255,255,0.85); }
11611192
button:disabled { opacity: 0.5; cursor: not-allowed; }
1162-
.btn-secondary { background: transparent; border: 1px solid var(--input-border); color: var(--fg); }
1193+
.btn-secondary { background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.6); color: var(--fg); }
1194+
.btn-secondary:hover { background: rgba(255,255,255,0.15); border-color: rgba(255,255,255,0.85); }
11631195
.btn-row { display: flex; gap: 6px; margin-top: 8px; }
11641196
.btn-row button { flex: 1; margin-top: 0; }
11651197
.btn-danger { background: var(--error); }

extension/templates/platforms/android.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- TestPilot-Template-Version: 2 -->
1+
<!-- TestPilot-Template-Version: 3 -->
22
# Android/Flutter 平台蓝本规则(platform = "android")
33

44
> 本文件定义 Android 原生应用和 Flutter 应用蓝本的完整规则。
@@ -7,6 +7,24 @@
77
88
---
99

10+
## 零、生成蓝本前必须先通读源代码(强制执行)
11+
12+
**蓝本的唯一依据是代码,不是猜测,不是常识,不是用户描述。**
13+
14+
在写任何 JSON 之前,必须按顺序完成:
15+
16+
0. **先读 `testpilot/CHANGELOG.md`(如果存在)** — 了解当前已覆盖的功能和尚未测试的模块,避免重复写或漏写;如果不存在则跳过
17+
1. **读入口/路由文件** — 了解应用整体结构和页面列表(如 `main.dart``AndroidManifest.xml`
18+
2. **读每个页面的 UI 文件** — 找出所有可操作元素(按钮、输入框、下拉框、导航项)
19+
3. **记录元素的真实标识**`hint` / `label` / `contentDescription` / `tooltip`(这是选择器的唯一来源)
20+
4. **读业务逻辑** — 确认每个操作的真实结果(跳转哪里、显示什么文字)
21+
5. **确认提示方式** — 成功/失败提示是 SnackBar/Toast(瞬态,**不可断言**)还是持久化 Text(可断言)
22+
6. **列出已实现功能** — 代码里有什么就测什么,未实现的功能不写蓝本
23+
24+
**禁止跳过代码阅读直接生成蓝本。凭想象写的选择器和断言几乎必然失败。**
25+
26+
---
27+
1028
## 一、必填字段
1129

1230
| 字段 | 说明 | 示例 |

extension/templates/platforms/desktop.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- TestPilot-Template-Version: 2 -->
1+
<!-- TestPilot-Template-Version: 3 -->
22
# Windows 桌面应用平台蓝本规则(platform = "desktop")
33

44
> 本文件定义 Windows 桌面应用(WPF/WinForms/Electron/Qt 等)蓝本的完整规则。
@@ -7,6 +7,24 @@
77
88
---
99

10+
## 零、生成蓝本前必须先通读源代码(强制执行)
11+
12+
**蓝本的唯一依据是代码,不是猜测,不是常识,不是用户描述。**
13+
14+
在写任何 JSON 之前,必须按顺序完成:
15+
16+
0. **先读 `testpilot/CHANGELOG.md`(如果存在)** — 了解当前已覆盖的功能和尚未测试的模块,避免重复写或漏写;如果不存在则跳过
17+
1. **读主窗口/入口文件** — 了解应用结构(如 `MainWindow.xaml``main.py``app.py`
18+
2. **读每个窗口的 UI 文件** — 找出所有控件,记录真实的 `Name``AutomationId``Content` 属性
19+
3. **记录元素的真实标识**`automationid:xxx``name:控件显示文字`(选择器的唯一来源)
20+
4. **读事件处理逻辑** — 确认每个按钮点击的真实结果(弹出什么窗口、显示什么文字)
21+
5. **确认提示方式** — 成功/失败提示是 `MessageBox`(阻塞弹窗,需 click 关闭)还是标签文字(可断言)
22+
6. **列出已实现功能** — 代码里有什么就测什么,未实现的功能不写蓝本
23+
24+
**禁止跳过代码阅读直接生成蓝本。凭想象写的选择器和断言几乎必然失败。**
25+
26+
---
27+
1028
## 一、必填字段
1129

1230
| 字段 | 说明 | 示例 |

extension/templates/platforms/ios.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- TestPilot-Template-Version: 2 -->
1+
<!-- TestPilot-Template-Version: 3 -->
22
# iOS/SwiftUI 平台蓝本规则(platform = "ios")
33

44
> 本文件定义 iOS 原生应用和 SwiftUI 应用蓝本的完整规则。
@@ -7,6 +7,24 @@
77
88
---
99

10+
## 零、生成蓝本前必须先通读源代码(强制执行)
11+
12+
**蓝本的唯一依据是代码,不是猜测,不是常识,不是用户描述。**
13+
14+
在写任何 JSON 之前,必须按顺序完成:
15+
16+
0. **先读 `testpilot/CHANGELOG.md`(如果存在)** — 了解当前已覆盖的功能和尚未测试的模块,避免重复写或漏写;如果不存在则跳过
17+
1. **读入口/路由文件** — 了解应用整体结构和页面列表(如 `ContentView.swift``@main App`
18+
2. **读每个页面的 UI 文件** — 找出所有可操作元素(Button、TextField、NavigationLink 等)
19+
3. **记录 accessibilityIdentifier**`.accessibilityIdentifier("xxx")` 是选择器的唯一来源,没有则无法定位
20+
4. **读业务逻辑** — 确认每个操作的真实结果(跳转哪里、显示什么文字)
21+
5. **确认提示方式** — 成功/失败提示是 `.alert()`(瞬态,**不可断言**)还是持久化 `Text`(可断言)
22+
6. **列出已实现功能** — 代码里有什么就测什么,未实现的功能不写蓝本
23+
24+
**禁止跳过代码阅读直接生成蓝本。凭想象写的选择器和断言几乎必然失败。**
25+
26+
---
27+
1028
## 一、必填字段
1129

1230
| 字段 | 说明 | 示例 |

extension/templates/platforms/miniprogram.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- TestPilot-Template-Version: 2 -->
1+
<!-- TestPilot-Template-Version: 3 -->
22
# 微信小程序平台蓝本规则(platform = "miniprogram")
33

44
> 本文件定义微信小程序蓝本的完整规则。
@@ -7,6 +7,23 @@
77
88
---
99

10+
## 零、生成蓝本前必须先通读源代码(强制执行)
11+
12+
**蓝本的唯一依据是代码,不是猜测,不是常识,不是用户描述。**
13+
14+
在写任何 JSON 之前,必须按顺序完成:
15+
16+
0. **先读 `testpilot/CHANGELOG.md`(如果存在)** — 了解当前已覆盖的功能和尚未测试的模块,避免重复写或漏写;如果不存在则跳过
17+
1. **`app.json`** — 了解所有页面路由和 TabBar 配置
18+
2. **读每个页面的 `.wxml` 文件** — 找出所有可操作元素,记录真实的 `class``placeholder``bindtap` 属性
19+
3. **读对应的 `.js` 文件** — 确认每个操作的真实结果(跳转哪里、显示什么文字)
20+
4. **确认提示方式** — 成功/失败提示是 `wx.showToast()`(瞬态,**不可断言**)还是页面内文字节点(可断言)
21+
5. **列出已实现功能** — 代码里有什么就测什么,未实现的功能不写蓝本
22+
23+
**禁止跳过代码阅读直接生成蓝本。凭想象写的选择器和断言几乎必然失败。**
24+
25+
---
26+
1027
## 一、必填字段
1128

1229
| 字段 | 说明 | 示例 |

extension/templates/platforms/web.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
1-
<!-- TestPilot-Template-Version: 2 -->
1+
<!-- TestPilot-Template-Version: 3 -->
22
# Web 平台蓝本规则(platform = "web")
33

44
> 本文件定义 Web 应用(React/Vue/Angular/纯HTML)蓝本的完整规则。
55
> 生成蓝本前**必须**通读本文件,不得跳过任何章节。
66
77
---
88

9+
## 零、生成蓝本前必须先通读源代码(强制执行)
10+
11+
**蓝本的唯一依据是代码,不是猜测,不是常识,不是用户描述。**
12+
13+
在写任何 JSON 之前,必须按顺序完成:
14+
15+
0. **先读 `testpilot/CHANGELOG.md`(如果存在)** — 了解当前已覆盖的功能和尚未测试的模块,避免重复写或漏写;如果不存在则跳过
16+
1. **读入口/路由文件** — 了解页面结构和路由配置(如 `App.js``router/index.js``index.html`
17+
2. **读每个页面的模板/HTML** — 找出所有可操作元素,记录真实的 `id``class``name` 属性
18+
3. **记录元素的真实选择器** — 只用代码中实际存在的 `#id` 或稳定 `.class`,禁止猜测
19+
4. **读业务逻辑** — 确认每个操作的真实结果(跳转哪里、显示什么文字、调用什么 API)
20+
5. **确认提示方式** — 成功/失败提示是短暂 Toast(不可断言)还是持久化 DOM 元素(可断言)
21+
6. **列出已实现功能** — 代码里有什么就测什么,未实现的功能不写蓝本
22+
23+
**禁止跳过代码阅读直接生成蓝本。凭想象写的选择器和断言几乎必然失败。**
24+
25+
---
26+
927
## 一、必填字段
1028

1129
| 字段 | 说明 | 示例 |

0 commit comments

Comments
 (0)