纲要
本文围绕 Claude Code 驱动的测试闭环展开,核心内容如下:
Claude Code测试流程- 测试计划生成
- 测试工程结构初始化
- 测试执行与 HTML 报告输出
- 关键概念
- AI 编程时代测试的价值
- 高风险功能识别
- 真实断言与无效测试
- 项目范围
003-fullstack/frontend003-fullstack/backenduni-app
- 补充代码示例
Node.js内置node:testJUnit 5VitestPlaywright- 静态 HTML 测试报告
- 适用版本
Node.js 18+JUnit 5.10+Vitest 2.xPlaywright 1.4xSpring Boot 3.3.x
背景:为什么 AI 编程时代更需要测试
AI 编程工具能够在极短时间内生成可运行代码,但这并不意味着可以跳过测试。Claude Code 等工具在生成业务代码时,可能无法完全理解边界条件、异常操作、数据一致性以及多模块交互。测试的本质不是单纯寻找 bug,而是保障功能稳定、用户体验正常、数据安全可靠,并最终使项目具备上线条件。
成熟开发流程应遵循"需求 → 开发 → 测试 → 修复 → 上线 → 持续优化"的闭环。在这个闭环中,测试不是上线前的简单页面点击,而是一套完整体系,覆盖功能测试、接口测试、压力测试、安全测试、兼容性测试、自动化测试、用户体验测试和业务逻辑验证。
#mermaid-svg-8mtORVii0V40stYu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8mtORVii0V40stYu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8mtORVii0V40stYu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8mtORVii0V40stYu .error-icon{fill:#552222;}#mermaid-svg-8mtORVii0V40stYu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8mtORVii0V40stYu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8mtORVii0V40stYu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8mtORVii0V40stYu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8mtORVii0V40stYu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8mtORVii0V40stYu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8mtORVii0V40stYu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8mtORVii0V40stYu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8mtORVii0V40stYu .marker.cross{stroke:#333333;}#mermaid-svg-8mtORVii0V40stYu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8mtORVii0V40stYu p{margin:0;}#mermaid-svg-8mtORVii0V40stYu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8mtORVii0V40stYu .cluster-label text{fill:#333;}#mermaid-svg-8mtORVii0V40stYu .cluster-label span{color:#333;}#mermaid-svg-8mtORVii0V40stYu .cluster-label span p{background-color:transparent;}#mermaid-svg-8mtORVii0V40stYu .label text,#mermaid-svg-8mtORVii0V40stYu span{fill:#333;color:#333;}#mermaid-svg-8mtORVii0V40stYu .node rect,#mermaid-svg-8mtORVii0V40stYu .node circle,#mermaid-svg-8mtORVii0V40stYu .node ellipse,#mermaid-svg-8mtORVii0V40stYu .node polygon,#mermaid-svg-8mtORVii0V40stYu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8mtORVii0V40stYu .rough-node .label text,#mermaid-svg-8mtORVii0V40stYu .node .label text,#mermaid-svg-8mtORVii0V40stYu .image-shape .label,#mermaid-svg-8mtORVii0V40stYu .icon-shape .label{text-anchor:middle;}#mermaid-svg-8mtORVii0V40stYu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8mtORVii0V40stYu .rough-node .label,#mermaid-svg-8mtORVii0V40stYu .node .label,#mermaid-svg-8mtORVii0V40stYu .image-shape .label,#mermaid-svg-8mtORVii0V40stYu .icon-shape .label{text-align:center;}#mermaid-svg-8mtORVii0V40stYu .node.clickable{cursor:pointer;}#mermaid-svg-8mtORVii0V40stYu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8mtORVii0V40stYu .arrowheadPath{fill:#333333;}#mermaid-svg-8mtORVii0V40stYu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8mtORVii0V40stYu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8mtORVii0V40stYu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8mtORVii0V40stYu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8mtORVii0V40stYu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8mtORVii0V40stYu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8mtORVii0V40stYu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8mtORVii0V40stYu .cluster text{fill:#333;}#mermaid-svg-8mtORVii0V40stYu .cluster span{color:#333;}#mermaid-svg-8mtORVii0V40stYu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8mtORVii0V40stYu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8mtORVii0V40stYu rect.text{fill:none;stroke-width:0;}#mermaid-svg-8mtORVii0V40stYu .icon-shape,#mermaid-svg-8mtORVii0V40stYu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8mtORVii0V40stYu .icon-shape p,#mermaid-svg-8mtORVii0V40stYu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8mtORVii0V40stYu .icon-shape .label rect,#mermaid-svg-8mtORVii0V40stYu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8mtORVii0V40stYu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8mtORVii0V40stYu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8mtORVii0V40stYu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
需求
开发
测试
发现问题?
修复
上线
持续优化
测试对象与范围裁剪
本次测试范围包含三个项目:003-fullstack 下的 frontend 与 backend,以及 uni-app 跨端应用。Java 后端项目与后台管理系统暂不纳入本轮执行范围,但可沿用相同流程扩展。
测试输出统一集中到 008-project-test 目录,其中测试计划放入 test-plans,测试报告放入 test-reports。这样可以将测试产物与业务代码解耦,避免后续在多项目中查找测试文档。
dir
workspace/
├── 003-fullstack/
│ ├── frontend/
│ └── backend/
├── 008-project-test/
│ ├── test-plans/
│ └── test-reports/
└── uni-app/
测试计划生成:以自然语言驱动 Claude Code
在正式测试前,应先让 Claude Code 分析项目,生成分层测试计划。测试计划提示词需要明确项目路径、分析维度、输出位置以及分项目输出要求。以下是一个可直接使用的测试计划生成提示词模板:
text
进入测试阶段,先完整分析当前项目:
项目路径:
- /workspace/003-fullstack/frontend
- /workspace/003-fullstack/backend
- /workspace/uni-app
要求:
1. 识别每个项目的技术栈、目录结构、启动方式
2. 找出每个项目的核心业务模块
3. 找出高风险功能,特别关注资金相关、安全相关、兼容性相关
4. 设计分层测试方案
5. 不要立即写代码,先输出测试计划到 /workspace/008-project-test/test-plans
6. 按不同项目分别输出测试计划,不要合并到同一文档
该提示词将分析维度拆分为技术栈识别、核心业务模块、高风险功能识别与测试方案设计四部分,并要求按项目拆分输出,避免多个项目的计划混在一个文档中。
从生成结果看,frontend 项目会识别出 Excel 导出、图表绘制、localStorage、页面跳转等高风险或兼容性相关功能;backend 项目会重点识别密码存储、加密、SQL 注入等安全类风险,并输出 API 接口清单与接口测试用例;uni-app 会结合移动端特性,剔除不涉及的 Excel 导出能力,并生成跨端差异相关风险清单。
测试工程结构初始化:隔离测试代码与业务代码
测试代码不应侵入业务代码。初始化测试工程时,需要新增 test 或 tests 目录,并让 Claude Code 自行配置测试框架、测试命令和报告输出目录。
text
请基于以上三份测试计划,为项目创建测试工程结构。
要求:
1. 不影响现有业务代码
2. 新增 test 或 tests 目录,集中存放测试相关代码
3. 配置测试框架
4. 配置测试命令
5. 配置测试报告输出目录
6. 给出每个测试文件的作用说明
执行后,三个项目均会生成独立的 test 或 tests 目录。frontend 项目通常包含单元测试、组件测试、集成测试和端到端测试;backend 项目会覆盖安全测试、性能测试和 API 接口测试;uni-app 项目则包含跨端相关测试目录。
目录结构可简化为:
dir
003-fullstack/
├── frontend/
│ ├── src/
│ └── tests/
│ ├── unit/
│ ├── e2e/
│ └── reports/
└── backend/
├── src/
└── tests/
├── unit/
├── integration/
├── security/
└── performance/
uni-app/
├── src/
└── tests/
├── unit/
└── e2e/
初始化完成之后,建议先手动检查业务代码是否被改动。如果发现业务代码发生变化,应重新调整提示词,明确"只新增测试相关内容,不修改原有业务代码"的约束条件。
断言与无效测试:从 expect(true).toBe(true) 到真实断言
断言是测试的核心,它表示对系统行为的预期。例如,设定一个安全等级预期后,只有测试结果达到该预期,断言才算通过;如果结果偏离预期,则测试失败。断言必须描述真实业务行为,而不是"永远为真"的无效校验。
无效测试示例:
js
expect(true).toBe(true)
这种测试只是不断验证一个本就为真的条件,无法发现业务缺陷,还会浪费测试资源。真正有效的断言需要绑定具体输入、输出或状态变化。
以下示例基于 Node.js 18+ 内置测试运行器,展示一个真实断言。该代码无需额外依赖,保存后可使用 node --test 直接运行。
js
// test/assert-demo.test.js
const assert = require('node:assert/strict');
const { test } = require('node:test');
function add(a, b) {
return a + b;
}
test('add returns the sum of two numbers', () => {
assert.equal(add(2, 3), 5);
assert.equal(add(-1, 1), 0);
});
运行命令如下:
bash
node --test test/assert-demo.test.js
如果后端采用 Spring Boot 与 JUnit 5,可参考以下断言示例。该示例仅用于展示断言写法,实际项目中应替换为真实业务对象。
java
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class CalculatorTest {
@Test
void shouldAddTwoNumbers() {
assertEquals(5, Calculator.add(2, 3));
}
static class Calculator {
static int add(int a, int b) {
return a + b;
}
}
}
测试执行与 HTML 报告生成
测试执行阶段需要将测试计划转化为实际测试行为。提示词应强调"优先测试最核心业务流程""严格按计划执行""真实断言""失败可追溯"以及"使用 HTML 报告"。
text
请优先为项目的最核心业务流程进行测试。
要求:
1. 严格按照测试计划执行
2. 覆盖所有功能点,如登录、注册、增删改查
3. 每个步骤都要有真实断言
4. 测试失败时自动截图;无法截图时整理完整测试步骤
5. 测试完成后生成 HTML 测试报告
6. 不要使用类似 expect(true).toBe(true) 的无效测试
执行完成后,backend 项目生成 HTML 报告,显示 21 个测试全部通过;frontend 项目总计 76 个测试全部通过;uni-app 项目同样为 100% 通过率。如果测试失败,应将失败原因或日志重新提交给 Claude Code 进行修复,然后按相同流程重新生成报告。
HTML 报告比 Markdown 更适合分发给非技术人员,例如团队负责人或项目相关方。报告中应包含测试项目、通过率、用例总数和失败项列表。
API 速览
本节梳理测试过程中可能使用的核心 API 和命令。
| 库或工具 | 适用版本 | 核心 API / 命令 | 说明 |
|---|---|---|---|
Node.js 内置测试运行器 |
18+ |
test(name, fn) |
注册一个测试用例 |
Node.js 内置断言 |
18+ |
assert.equal(actual, expected) |
验证实际值与期望值严格相等 |
JUnit 5 |
5.10+ |
@Test |
标记一个测试方法 |
JUnit 5 |
5.10+ |
assertEquals(expected, actual) |
验证期望值与实际值相等 |
Vitest |
2.x |
describe / it / expect |
前端单元测试与组件测试 |
Playwright |
1.4x |
page.goto / page.click / expect(page).toHaveURL |
端到端测试与截图 |
如果你使用 Vitest 对前端函数进行断言,可以这样组织测试:
js
// test/unit/example.test.js
import { describe, it, expect } from 'vitest';
function formatDate(date) {
return date.toISOString().slice(0, 10);
}
describe('formatDate', () => {
it('returns YYYY-MM-DD format', () => {
expect(formatDate(new Date('2026-09-03T00:00:00Z'))).toBe('2026-09-03');
});
});
如果使用 Playwright 做端到端测试,失败时自动截图的关键逻辑如下:
js
import { test, expect } from '@playwright/test';
test('login page works', async ({ page }) => {
await page.goto('http://localhost:5173/login');
await expect(page).toHaveTitle(/登录/);
});
Demo 示例
下面提供一个可直接运行的 HTML 测试报告模板,用于展示后端核心业务测试结果。它不依赖任何外部服务,直接在浏览器中打开即可查看。
html
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>backend 核心业务测试报告</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
margin: 40px;
background: #f8fafc;
color: #0f172a;
}
h1 {
font-size: 24px;
margin-bottom: 8px;
}
.summary {
display: flex;
gap: 24px;
margin: 24px 0;
}
.card {
background: #ffffff;
border: 1px solid #e2e8f0;
border-radius: 12px;
padding: 16px 24px;
min-width: 140px;
}
.card .label {
font-size: 12px;
color: #64748b;
}
.card .value {
font-size: 28px;
font-weight: 700;
margin-top: 4px;
}
.passed {
color: #16a34a;
}
table {
width: 100%;
border-collapse: collapse;
background: #ffffff;
border: 1px solid #e2e8f0;
border-radius: 12px;
overflow: hidden;
}
th, td {
padding: 12px 16px;
border-bottom: 1px solid #e2e8f0;
text-align: left;
}
th {
background: #f1f5f9;
font-weight: 600;
}
tr:last-child td {
border-bottom: none;
}
</style>
</head>
<body>
<h1>backend 核心业务测试报告</h1>
<p>测试执行时间:2026-09-03 16:02:17</p>
<div class="summary">
<div class="card">
<div class="label">通过率</div>
<div class="value passed">100%</div>
</div>
<div class="card">
<div class="label">测试用例总数</div>
<div class="value">21</div>
</div>
<div class="card">
<div class="label">通过用例</div>
<div class="value passed">21</div>
</div>
<div class="card">
<div class="label">失败用例</div>
<div class="value">0</div>
</div>
</div>
<table>
<thead>
<tr>
<th>测试模块</th>
<th>测试用例</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr><td>认证接口</td><td>登录成功返回 token</td><td>通过</td></tr>
<tr><td>用户接口</td><td>注册后数据库存在用户</td><td>通过</td></tr>
<tr><td>核心业务</td><td>创建、查询、更新、删除数据</td><td>通过</td></tr>
<tr><td>安全测试</td><td>SQL 注入参数返回参数校验错误</td><td>通过</td></tr>
<tr><td>安全测试</td><td>密码存储使用 BCrypt 加密</td><td>通过</td></tr>
</tbody>
</table>
</body>
</html>
运行说明
将上述内容保存为 test-report.html,使用浏览器直接打开即可查看报告。若需要动态生成报告,可以在 Claude Code 执行测试后,将 JSON 格式的测试结果渲染到该页面中。
代码说明
该 HTML 文件通过 CSS 卡片和表格展示测试汇总信息,适合替代 Markdown 报告,便于分发给非技术人员。页面中的测试数据为静态示例,实际项目中可以将其替换为测试框架输出的真实结果。
技术点总结
该 Demo 演示了以下技术点:使用 HTML 静态页面作为轻量级测试报告载体;使用卡片式布局展示通过率、用例总数和失败数;使用表格展示模块级测试结果;通过浏览器直接打开实现零依赖查看。
参考文档
官方文档
- Claude Code 官方文档
- Anthropic 官方文档
- Node.js Test runner
- Vitest 官方文档
- JUnit 5 User Guide
- Spring Boot Testing
- Playwright 官方文档
- uni-app 官方文档
参考链接
总结
本文完整梳理了基于 Claude Code 的多人项目测试闭环:先生成分层测试计划,再初始化隔离于业务代码的测试工程结构,然后通过真实断言执行核心业务流程测试,最后输出 HTML 测试报告。涉及的技术栈包括 Claude Code、Node.js 内置测试运行器、JUnit 5、Vitest、Playwright、Spring Boot 与 uni-app。高风险功能识别重点关注资金安全、密码存储、SQL 注入、兼容性差异等问题。测试流程强调真实断言,避免 expect(true).toBe(true) 一类无效校验。