# Action: Validate With File 运行测试并验证实现,记录结果到 validation.md,支持 Gemini 辅助分析测试覆盖率和质量。 ## Purpose 执行测试验证流程,包括: - 运行单元测试 - 运行集成测试 - 检查代码覆盖率 - 生成验证报告 - 分析失败原因 ## Preconditions - [ ] state.initialized === true - [ ] state.status === 'running' - [ ] state.develop.completed_count > 0 || state.debug.confirmed_hypothesis !== null ## Session Setup ```javascript const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString() const sessionFolder = `.workflow/.loop/${state.session_id}` const validateFolder = `${sessionFolder}/validate` const validationPath = `${validateFolder}/validation.md` const testResultsPath = `${validateFolder}/test-results.json` const coveragePath = `${validateFolder}/coverage.json` ``` --- ## Execution ### Step 1: 运行测试 ```javascript console.log('\n运行测试...') // 检测测试框架 const packageJson = JSON.parse(Read('package.json')) const testScript = packageJson.scripts?.test || 'npm test' // 运行测试并捕获输出 const testResult = await Bash({ command: testScript, timeout: 300000 // 5分钟 }) // 解析测试输出 const testResults = parseTestOutput(testResult.stdout) ``` ### Step 2: 检查覆盖率 ```javascript // 运行覆盖率检查 let coverageData = null if (packageJson.scripts?.['test:coverage']) { const coverageResult = await Bash({ command: 'npm run test:coverage', timeout: 300000 }) // 解析覆盖率报告 coverageData = parseCoverageReport(coverageResult.stdout) Write(coveragePath, JSON.stringify(coverageData, null, 2)) } ``` ### Step 3: Gemini 辅助分析 ```bash ccw cli -p " PURPOSE: Analyze test results and coverage Success criteria: Identify quality issues and suggest improvements TASK: • Analyze test execution results • Review code coverage metrics • Identify missing test cases • Suggest quality improvements • Verify requirements coverage MODE: analysis CONTEXT: @${testResultsPath} @${coveragePath} @${sessionFolder}/develop/progress.md EXPECTED: - Quality assessment report - Failed tests analysis - Coverage gaps identification - Improvement recommendations - Pass/Fail decision with rationale CONSTRAINTS: Evidence-based quality assessment " --tool gemini --mode analysis --rule analysis-review-code-quality ``` ### Step 4: 生成验证报告 ```javascript const timestamp = getUtc8ISOString() const iteration = (state.validate.test_results?.length || 0) + 1 const validationReport = `# Validation Report **Session ID**: ${state.session_id} **Task**: ${state.task_description} **Validated**: ${timestamp} --- ## Iteration ${iteration} - Validation Run ### Test Execution Summary | Metric | Value | |--------|-------| | Total Tests | ${testResults.total} | | Passed | ${testResults.passed} | | Failed | ${testResults.failed} | | Skipped | ${testResults.skipped} | | Duration | ${testResults.duration_ms}ms | | **Pass Rate** | **${(testResults.passed / testResults.total * 100).toFixed(1)}%** | ### Coverage Report ${coverageData ? ` | File | Statements | Branches | Functions | Lines | |------|------------|----------|-----------|-------| ${coverageData.files.map(f => `| ${f.path} | ${f.statements}% | ${f.branches}% | ${f.functions}% | ${f.lines}% |`).join('\n')} **Overall Coverage**: ${coverageData.overall.statements}% ` : '_No coverage data available_'} ### Failed Tests ${testResults.failed > 0 ? ` ${testResults.failures.map(f => ` #### ${f.test_name} - **Suite**: ${f.suite} - **Error**: ${f.error_message} - **Stack**: \`\`\` ${f.stack_trace} \`\`\` `).join('\n')} ` : '_All tests passed_'} ### Gemini Quality Analysis ${geminiAnalysis} ### Recommendations ${recommendations.map(r => `- ${r}`).join('\n')} --- ## Validation Decision **Result**: ${testResults.passed === testResults.total ? '✅ PASS' : '❌ FAIL'} **Rationale**: ${validationDecision} ${testResults.passed !== testResults.total ? ` ### Next Actions 1. Review failed tests 2. Debug failures using action-debug-with-file 3. Fix issues and re-run validation ` : ` ### Next Actions 1. Consider code review 2. Prepare for deployment 3. Update documentation `} ` // 写入验证报告 Write(validationPath, validationReport) ``` ### Step 5: 保存测试结果 ```javascript const testResultsData = { iteration, timestamp, summary: { total: testResults.total, passed: testResults.passed, failed: testResults.failed, skipped: testResults.skipped, pass_rate: (testResults.passed / testResults.total * 100).toFixed(1), duration_ms: testResults.duration_ms }, tests: testResults.tests, failures: testResults.failures, coverage: coverageData?.overall || null } Write(testResultsPath, JSON.stringify(testResultsData, null, 2)) ``` --- ## State Updates ```javascript const validationPassed = testResults.failed === 0 && testResults.passed > 0 return { stateUpdates: { validate: { test_results: [...(state.validate.test_results || []), testResultsData], coverage: coverageData?.overall.statements || null, passed: validationPassed, failed_tests: testResults.failures.map(f => f.test_name), last_run_at: getUtc8ISOString() }, last_action: 'action-validate-with-file' }, continue: true, message: validationPassed ? `验证通过 ✅\n测试: ${testResults.passed}/${testResults.total}\n覆盖率: ${coverageData?.overall.statements || 'N/A'}%` : `验证失败 ❌\n失败: ${testResults.failed}/${testResults.total}\n建议进入调试模式` } ``` ## Test Output Parsers ### Jest/Vitest Parser ```javascript function parseJestOutput(stdout) { const testPattern = /Tests:\s+(\d+) passed.*?(\d+) failed.*?(\d+) total/ const match = stdout.match(testPattern) return { total: parseInt(match[3]), passed: parseInt(match[1]), failed: parseInt(match[2]), // ... parse individual test results } } ``` ### Pytest Parser ```javascript function parsePytestOutput(stdout) { const summaryPattern = /(\d+) passed.*?(\d+) failed.*?(\d+) error/ // ... implementation } ``` ## Error Handling | Error Type | Recovery | |------------|----------| | Tests don't run | 检查测试脚本配置,提示用户 | | All tests fail | 建议进入 debug 模式 | | Coverage tool missing | 跳过覆盖率检查,仅运行测试 | | Timeout | 增加超时时间或拆分测试 | ## Validation Report Template 参考 [templates/validation-template.md](../../templates/validation-template.md) ## CLI Integration ### 质量分析 ```bash ccw cli -p "PURPOSE: Analyze test results and coverage... TASK: • Review results • Identify gaps • Suggest improvements MODE: analysis CONTEXT: @test-results.json @coverage.json EXPECTED: Quality assessment " --tool gemini --mode analysis --rule analysis-review-code-quality ``` ### 测试生成 (如覆盖率低) ```bash ccw cli -p "PURPOSE: Generate missing test cases... TASK: • Analyze uncovered code • Write tests MODE: write CONTEXT: @coverage.json @src/**/* EXPECTED: Test code " --tool gemini --mode write --rule development-generate-tests ``` ## Next Actions (Hints) - 验证通过: `action-complete` (完成循环) - 验证失败: `action-debug-with-file` (调试失败测试) - 覆盖率低: `action-develop-with-file` (添加测试) - 用户选择: `action-menu` (返回菜单)