Files
homeutils/docs/superpowers/plans/2026-08-05-ai-test-one-click-workflow.md
T
2026-08-05 14:03:52 +08:00

234 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AI Test One-Click Workflow Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 在“项目与增量”Tab 内一键完成增量分析、单测生成、Maven/JaCoCo 验证与覆盖率展示,并在首次使用时自动发现和保存 JDK 8、Maven 与 CodeFree 配置。
**Architecture:** 新增独立的工具链发现器,只负责从保存值、环境、运行时和 Maven 输出解析路径;`AiTestPane` 通过单个后台任务串联现有 `analyze` 与 `generateAndVerify`,领域工作流保持不变。界面通过稳定的控件 ID 和状态转换测试验证第一 Tab 操作与结果自动定位。
**Tech Stack:** Java 17 编译、目标业务 JDK 8、JavaFX 17、Maven 3.8.6、JUnit 5、Mockito、CodeFree CLI 0.3.6、JaCoCo。
## Global Constraints
- 不使用子代理,当前会话单线程实施。
- 用户保存配置优先,自动探测仅补齐空值或不存在的首次配置。
- Windows 兜底路径只有真实存在时才使用;macOS/Linux 不写入 Windows 路径。
- 不修改 CodeFree CLI 协议、质量规范格式、合并审核规则和手机 UI 自动化插件。
- 保留 `master...DEV_1156339215001460262` 与最新异步请求防覆盖逻辑。
- 不暂存或修改现有未跟踪审计文件、截图目录和 SQL 文件。
---
### Task 1: 默认工具链自动发现
**Files:**
- Create: `src/main/java/com/example/workutils/biz/aitest/config/ToolchainSettingsDetector.java`
- Modify: `src/main/java/com/example/workutils/biz/aitest/config/AiTestSettingsService.java`
- Test: `src/test/java/com/example/workutils/biz/aitest/config/ToolchainSettingsDetectorTest.java`
- Test: `src/test/java/com/example/workutils/biz/aitest/config/AiTestSettingsServiceTest.java`
**Interfaces:**
- Produces: `AiTestSettings ToolchainSettingsDetector.complete(AiTestSettings saved)`。
- Consumes: 环境变量读取函数、系统属性读取函数、文件存在性函数,以及返回 `mvn -version` 输出的函数,均通过构造参数注入以便测试。
- `AiTestSettingsService.load()` 在文件不存在时调用发现器;配置文件存在时只补齐空路径,不覆盖有效保存值。
- [ ] **Step 1: 写失败测试**
```java
@Test
void discoversJdkRootFromJavaHomeJreAndParsesMavenHome() {
ToolchainSettingsDetector detector = fixture(
Map.of(), Map.of("java.home", "C:/Program Files/Java/jdk-1.8/jre"),
"Apache Maven 3.8.6\nMaven home: D:/bestpay-maven/apache-maven-3.8.6");
AiTestSettings result = detector.complete(AiTestSettings.defaults());
assertEquals(Path.of("C:/Program Files/Java/jdk-1.8"), result.jdk8Home());
assertEquals(Path.of("D:/bestpay-maven/apache-maven-3.8.6"), result.mavenHome());
}
```
同时覆盖:保存值优先、`JAVA_HOME`、`MAVEN_HOME`、`M2_HOME`、非 Windows 不使用 Windows 兜底、探测值被 `AiTestSettingsService` 保存。
- [ ] **Step 2: 运行测试并确认 RED**
Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -Dtest=ToolchainSettingsDetectorTest,AiTestSettingsServiceTest test`
Expected: FAIL,因为 `ToolchainSettingsDetector` 尚不存在且服务不会自动保存探测结果。
- [ ] **Step 3: 实现最小发现器**
```java
public AiTestSettings complete(AiTestSettings saved) {
Path jdk = usable(saved.jdk8Home()) ? saved.jdk8Home() : detectJdk8();
Path maven = usable(saved.mavenHome()) ? saved.mavenHome() : detectMaven();
return new AiTestSettings(jdk, maven, saved.codeFreeCommand(), saved.coverageTarget(),
saved.maxRepairRounds(), saved.codeFreeTimeout(), saved.mavenTimeout());
}
```
JDK 发现顺序为 `JAVA_HOME`、`java.home`、存在的 Windows 兜底;Maven 顺序为 `MAVEN_HOME`、`M2_HOME`、`mvn -version` 的 `Maven home:`、存在的 Windows 兜底。
- [ ] **Step 4: 运行聚焦测试并确认 GREEN**
Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -Dtest=ToolchainSettingsDetectorTest,AiTestSettingsServiceTest test`
Expected: 所有配置探测测试通过。
- [ ] **Step 5: 提交**
```powershell
git add src/main/java/com/example/workutils/biz/aitest/config/ToolchainSettingsDetector.java src/main/java/com/example/workutils/biz/aitest/config/AiTestSettingsService.java src/test/java/com/example/workutils/biz/aitest/config/ToolchainSettingsDetectorTest.java src/test/java/com/example/workutils/biz/aitest/config/AiTestSettingsServiceTest.java
git commit -m "feat: discover default AI test toolchain"
```
### Task 2: 一键协调执行链
**Files:**
- Create: `src/main/java/com/example/workutils/biz/aitest/application/AiTestOneClickRunner.java`
- Modify: `src/main/java/com/example/workutils/biz/aitest/AiTestPlugin.java`
- Modify: `src/main/java/com/example/workutils/biz/aitest/AiTestPane.java`
- Test: `src/test/java/com/example/workutils/biz/aitest/application/AiTestOneClickRunnerTest.java`
**Interfaces:**
- Produces: `AiTestRun AiTestOneClickRunner.run(AiTestRequest request, Consumer<AiTestProgress> progress)`。
- Consumes: `AiTestWorkflow.analyze` 与 `AiTestWorkflow.generateAndVerify`。
- 当分析结果不是 `ANALYZED` 时原样返回且不调用生成;分析成功时继续生成验证。
- [ ] **Step 1: 写失败测试**
```java
@Test
void generatesAndVerifiesAfterSuccessfulAnalysis() {
when(workflow.analyze(request, progress)).thenReturn(analyzed);
when(workflow.generateAndVerify(analyzed, progress)).thenReturn(ready);
assertSame(ready, runner.run(request, progress));
verify(workflow).generateAndVerify(analyzed, progress);
}
@Test
void stopsWhenAnalysisFails() {
when(workflow.analyze(request, progress)).thenReturn(failed);
assertSame(failed, runner.run(request, progress));
verify(workflow, never()).generateAndVerify(any(), any());
}
```
- [ ] **Step 2: 运行测试并确认 RED**
Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -Dtest=AiTestOneClickRunnerTest test`
Expected: FAIL,因为协调器尚不存在。
- [ ] **Step 3: 实现最小协调器并注入界面**
```java
public AiTestRun run(AiTestRequest request, Consumer<AiTestProgress> progress) {
AiTestRun analyzed = workflow.analyze(request, progress);
return analyzed.state() == AiTestRunState.ANALYZED
? workflow.generateAndVerify(analyzed, progress)
: analyzed;
}
```
`AiTestPane` 一键操作必须只调用一次 `runAsync`,确保 busy/progress 在完整链路结束后才复位。
- [ ] **Step 4: 运行测试并确认 GREEN**
Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -Dtest=AiTestOneClickRunnerTest,AiTestWorkflowTest test`
Expected: 协调器与既有工作流测试通过。
- [ ] **Step 5: 提交**
```powershell
git add src/main/java/com/example/workutils/biz/aitest/application/AiTestOneClickRunner.java src/main/java/com/example/workutils/biz/aitest/AiTestPlugin.java src/main/java/com/example/workutils/biz/aitest/AiTestPane.java src/test/java/com/example/workutils/biz/aitest/application/AiTestOneClickRunnerTest.java
git commit -m "feat: run AI test generation and coverage in one action"
```
### Task 3: 第一 Tab 操作与结果自动定位
**Files:**
- Modify: `src/main/java/com/example/workutils/biz/aitest/AiTestPane.java`
- Modify: `src/test/java/com/example/workutils/biz/aitest/AiTestPaneArchitectureTest.java`
**Interfaces:**
- 主按钮 ID:`generate-and-cover-action`,文本“生成单测并分析覆盖率”。
- 次按钮 ID:`analyze-only-action`,文本“仅分析增量”。
- 主 TabPane ID:`ai-test-main-tabs`;结果 TabPane ID:`ai-test-result-tabs`。
- 成功选择主 Tab“结果与合并”和内层 Tab“覆盖率”;失败选择内层 Tab“运行日志”。
- [ ] **Step 1: 写失败的 JavaFX 结构/状态测试**
```java
assertEquals("项目与增量", mainTabs.getSelectionModel().getSelectedItem().getText());
assertNotNull(pane.lookup("#generate-and-cover-action"));
assertNotNull(pane.lookup("#analyze-only-action"));
assertFalse(toolchainTab.isSelected());
```
增加可直接调用的包内结果呈现测试入口或提取无状态 `AiTestResultSelection`,分别断言 `READY_FOR_REVIEW` 选覆盖率、`FAILED` 选运行日志。
- [ ] **Step 2: 运行测试并确认 RED**
Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -Dtest=AiTestPaneArchitectureTest,AiTestResultSelectionTest test`
Expected: FAIL,因为主操作仍位于结果 Tab 且没有结果选择策略。
- [ ] **Step 3: 实现第一 Tab 操作区与选择策略**
```java
HBox projectActions = new HBox(10, generateAndCoverButton, analyzeOnlyButton);
VBox projectPage = page(selection, projectActions);
```
删除结果 Tab 中重复的“分析增量/生成并验证”操作,只保留执行中的“取消”。工具链异常时保持当前结果并提示进入“工具链”;正常成功或失败按状态切换结果子 Tab。
- [ ] **Step 4: 运行 UI 与插件聚焦测试并确认 GREEN**
Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -Dtest=AiTestPaneArchitectureTest,AiTestResultSelectionTest,AiTestPluginTest test`
Expected: 第一 Tab 操作、默认选择及结果定位测试全部通过。
- [ ] **Step 5: 提交**
```powershell
git add src/main/java/com/example/workutils/biz/aitest/AiTestPane.java src/test/java/com/example/workutils/biz/aitest/AiTestPaneArchitectureTest.java src/main/java/com/example/workutils/biz/aitest/ui/AiTestResultSelection.java src/test/java/com/example/workutils/biz/aitest/ui/AiTestResultSelectionTest.java
git commit -m "feat: expose one-click AI test workflow on project tab"
```
### Task 4: 真实项目回归与发布验证
**Files:**
- Modify only if a regression exposes a defect in files from Tasks 1-3.
- Verify: `src/test/java/com/example/workutils/biz/aitest/project/FtLoanCapitalCoreRegressionTest.java`
**Interfaces:**
- `master...DEV_1156339215001460262` 必须继续定位 `ft-loancapital-core-start` 并分析显式目标引用。
- 打包产物:`target/workutils-1.0.1-SNAPSHOT.jar`。
- [ ] **Step 1: 运行真实项目和 AI 插件测试**
Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -Dtest='com.example.workutils.biz.aitest.**,FtLoanCapitalCoreRegressionTest' test`
Expected: AI 插件测试与真实项目回归全部通过。
- [ ] **Step 2: 运行全量测试**
Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn test`
Expected: 0 failures、0 errors;仅允许既有 GUI 环境跳过项。
- [ ] **Step 3: 打包与差异检查**
Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -DskipTests package; git diff --check; git status --short`
Expected: BUILD SUCCESS、`git diff --check` 无输出,用户未跟踪文件保持未暂存。
- [ ] **Step 4: 提交验证阶段必要修复(如有)**
```powershell
git add -- <only-files-changed-by-this-plan>
git commit -m "fix: complete AI test one-click regression"
```
若没有必要修复则不创建空提交。