diff --git a/apps/slides/final-report.md b/apps/slides/final-report.md new file mode 100644 index 000000000..f8c2e04e5 --- /dev/null +++ b/apps/slides/final-report.md @@ -0,0 +1,792 @@ +--- +theme: default +addons: [] +title: Nomad 项目期末汇报 +info: false +author: uke +presenter: true +browserExporter: dev +download: false +twoslash: true +lineNumbers: true +monaco: true +selectable: true +record: false +colorSchema: auto +drawings: + enabled: false +fonts: + mono: "Fira Code, monospace" +layout: cover +transition: slide-left +mdc: true +--- + +# Nomad 项目期末汇报 + +Requirements as Code 方法实践 + +—— TODO 小组 + + + + + + + +--- +layout: center +transition: slide-left +--- + +# 目录 + +1. **演示环节** - 展示目前实现的核心业务功能 +2. **需求管理方法** - Requirements as Code 的创新实践 +3. **需求-设计-测试-实现的闭环** - 如何达成稳定复现代码 +4. **挑战与解决方案** - 当前测试框架的不足 +5. **GUI测试运行情况** - 通过率和改进 + + + +--- +layout: section +transition: slide-up +--- + +# 一、演示环节 + +展示目前实现的核心业务功能 + + + +--- +transition: slide-left +layout: section +--- + +# 二、需求管理方法 + +Requirements as Code 的创新实践 + + + +--- +transition: slide-up +layout: two-cols-header +--- + +## 2.1 传统需求管理的痛点 + +::left:: + +### 常见问题 + +- **需求与代码分离** + - Word/Excel 文档难以同步 + - 需求变更追踪困难 + - 代码和文档容易脱节 + +- **测试覆盖率难以量化** + - 无法准确知道哪些需求已测试 + - 人工统计费时费力 + - 容易遗漏边界场景 + +::right:: + +### AI 辅助开发的挑战 + +- **AI 生成测试的局限性** + - 容易产生"幻觉" + - 倾向于 Happy Path + - 遗漏异常场景和边界条件 + +- **追溯性差** + - 难以知道某个测试覆盖了哪个需求 + - 需求变更时难以找到相关测试 + - 缺乏自动化验证机制 + + + +--- +transition: slide-up +layout: center +--- + +## 2.2 我们的解决方案:Requirements as Code + +### 核心思想 + +将需求定义为 **TypeScript 代码**,纳入 **版本控制** + +### 关键优势 + +- **类型安全** - TypeScript 类型定义保证需求结构一致 +- **版本控制** - 需求变更可追溯,支持 Git Diff +- **模块化管理** - 按业务模块组织(用户、机票、订单、支付、UI/UX) +- **多应用共享** - 一次定义,多处消费(文档系统、主应用、覆盖率分析) + + + +--- +transition: slide-up +layout: two-cols-header +--- + +## 2.2 实现架构(结合 Monorepo) + +::left:: + +### 目录结构 + +``` +packages/requirements/ ← 需求定义包(核心) +├── src/data/ +│ ├── user-module.ts +│ ├── flight-module.ts +│ ├── order-module.ts +│ ├── payment-module.ts +│ └── ui-ux-module.ts +├── src/utils/ +│ └── traceability/ ← 需求追溯系统 +│ ├── parser.ts +│ ├── mapper.ts +│ └── reporter.ts +└── src/cli/ + └── coverage.ts ← 自动化覆盖率分析 +``` + +::right:: + +### 消费者应用 + +```typescript +apps/docs/ ← 文档系统 +├── components/ +│ ├── RequirementStats.tsx +│ ├── RequirementDetail.tsx +│ └── RequirementToc.tsx +└── content/docs/requirements/ + +apps/web/ ← 主应用 +├── app/_components/ +│ └── *.test.tsx ← 带需求标签的测试 +└── coverage-report.json ← 覆盖率报告 +``` + + + +--- +transition: slide-up +--- + +## 2.3 具体需求展示 + +### 需求定义 + +```typescript +const REQ_F01: Requirement = { + id: "REQ-F01", + module: "flight", + name: "航班搜索表单", + overview: + "本功能是用户发起机票查询流程的主入口,位于机票业务的首页。它提供了一个简洁、高效的表单,用于捕获用户的核心出行意图,包括行程类型(单程/往返)、出发地、目的地、日期和座舱等级,并将用户引导至包含详细航班信息的搜索结果页面。", + priority: "Must Have", + userStories: [ + { + id: "US-01", + content: + "作为一个有初步出行计划的用户,我希望能在首页清晰地看到并填写我的出发地、目的地和日期,以便快速启动航班搜索。", + }, + { + id: "US-02", + content: + "作为一个用户,我希望能选择单程或往返行程类型,以便系统返回符合我需求的航班结果。", + }, + ], +}; +``` + +--- +transition: slide-up +--- + +## 2.3 具体需求展示(续) + +### 验收标准定义 + +```typescript +{ + id: "场景7", + title: "交换出发地和目的地", + steps: [ + { + type: "given", + description: `用户已选择出发地为"上海",目的地为"北京"`, + }, + { + type: "when", + description: "用户点击交换按钮", + }, + { + type: "then", + description: `出发地应变为"北京",目的地应变为"上海"`, + }, + ], +} +``` + +--- +transition: slide-up +layout: center +--- + +## 2.3 需求数量与结构 + +| 模块 | 需求数量 | 验收场景数 | 优先级分布 | +| --------- | -------- | ---------- | ------------------------------ | +| 用户模块 | 12 | ~75 | Must: 6, Should: 6 | +| 机票模块 | 13 | ~95 | Must: 9, Should: 3, Could: 1 | +| 订单模块 | 12 | ~85 | Must: 8, Should: 4 | +| 支付模块 | 13 | ~75 | Must: 11, Should: 2 | +| UI/UX模块 | 12 | ~51 | Must: 8, Should: 4 | +| **总计** | **62** | **381** | Must: 42, Should: 19, Could: 1 | + + + +--- +transition: slide-left +layout: section +--- + +# 三、需求-设计-测试-实现的闭环 + +如何达成稳定复现代码 + + + +--- +transition: slide-up +--- + +## 3.1 设计思路:双向追溯系统 + +### 完整工作流程 + +```mermaid +graph LR + A[需求定义] --> B[JSDoc标签] + B --> C[测试代码] + C --> D[AST解析] + D --> E[覆盖率映射] + E --> F[覆盖率报告] + F --> G[文档展示] + G -.反馈.-> A +``` + +### 关键环节 + +1. **需求定义** → packages/requirements 定义 62 个需求、381 个场景 +2. **JSDoc标签** → @requirement, @scenario 标记测试 +3. **AST解析** → TypeScript Compiler API 提取标签 +4. **覆盖率映射** → 构建需求↔测试、场景↔测试的双向映射 +5. **覆盖率报告** → 识别未覆盖需求和场景 +6. **文档展示** → apps/docs 动态展示需求状态 + + + +--- +transition: slide-up +layout: two-cols-header +--- + +## 3.2 方法1:JSDoc 标签追溯 + +::left:: + +### 标签语法 + +```typescript +/** + * @requirement REQ-U01 ← 关联需求 + * @scenario 场景1 ← 关联验收场景 + */ +describe("PhoneVerificationForm", () => { + it("should render all form fields correctly", () => { + // 测试实现 + }); +}); +``` + +### 继承规则 + +- **文件级** → describe 块 → test 块 +- 子级标签覆盖父级标签 +- 支持多需求、多场景关联 + +::right:: + +### 实际示例 + +```typescript {*}{maxHeight:'400px'} +/** + * @requirement REQ-U01 + * Phone verification form component tests + */ + +describe("PhoneVerificationForm", () => { + /** + * @scenario 场景1: 表单正确渲染 + */ + it("should render all form fields", () => { + render(); + + expect(screen.getByLabelText(/手机号/)) + .toBeInTheDocument(); + expect(screen.getByLabelText(/验证码/)) + .toBeInTheDocument(); + }); + + /** + * @scenario 场景2: 验证码发送 + */ + it("should send verification code", + async () => { + // ... + }); +}); +``` + + + +--- +transition: slide-up +--- + +## 3.2 方法2:自动化覆盖率分析 + +### 实现原理 + +1. **AST 解析** - 使用 TypeScript Compiler API 解析测试文件 +2. **标签提取** - 提取 JSDoc 标签(@requirement, @scenario) +3. **映射构建** - 构建需求→测试、场景→测试的双向映射 +4. **标签验证** - 验证需求ID和场景ID是否有效 +5. **统计计算** - 计算覆盖率、识别未覆盖项 + +### 工具链路 + +```bash +pnpm test:ac-coverage # 生成覆盖率报告 +pnpm test:ac-coverage --json # JSON 格式输出 +``` + + + +--- +transition: slide-up +--- + +## 覆盖率报告内容 + +### 报告结构 + +- **总体覆盖率统计** + - 需求覆盖率 + - 场景覆盖率 + - 按优先级统计 + +- **各模块覆盖率** + - 用户模块:~80% + - 机票模块:~90% + - 订单模块:~50% + - 支付模块:~60% + - UI/UX模块:0% (<-- 不测试) + + + +--- +transition: slide-up +layout: two-cols-header +--- + +## 3.3 方法3:文档系统动态展示 + +::left:: + +### 文档组件 + +```tsx {*}{maxHeight:'400px'} +// MDX 文档 +import { userModule } + from '@nomad/requirements/data'; +import { + RequirementStats, + RequirementDetail +} from '@/components'; + +## 用户模块 + +用户模块包含 {userModule.requirements.length} +个功能需求。 + + + +{userModule.requirements.map((req) => ( + +))} +``` + +::right:: + +### 展示内容 + +- **需求统计表格** +- **需求详情卡片** +- **需求目录导航** + + + +--- +transition: slide-up +layout: two-cols-header +--- + +## 4.1 挑战1:需求覆盖率不均衡 + +::left:: + +### 现象 + +| 模块 | 覆盖率 | 状态 | +| --------- | ------ | --------- | +| 用户模块 | ~80% | ✅ 良好 | +| 机票模块 | ~90% | ✅ 良好 | +| 订单模块 | ~50% | ⚠️ 待改进 | +| 支付模块 | ~60% | ❌ 需补充 | +| UI/UX模块 | 0% | ❌ 需补充 | + +### 根因分析 + +1. **组件设计问题** + - 部分组件未遵循单一职责原则 + - 业务逻辑与 UI 耦合,难以拆分测试 + +::right:: + +### 根因分析(续) + +2. **测试优先级** + - 团队优先保证核心业务流程 + - 用户注册、订单查询优先实现 + +3. **AI 辅助局限** + - AI 生成的测试倾向于 Happy Path + - 边界场景覆盖不足 + +### 解决方案 + +- 重构支付模块:分离 Base 组件(UI)和 Web Adapter(业务逻辑) +- 利用覆盖率报告:优先补充 Must Have 需求的测试 +- 建立测试模板:标准化 JSDoc 标签使用规范 + + + +--- +transition: slide-up +layout: two-cols-header +--- + +## 4.3 挑战2:Monorepo 维护复杂度 + +::left:: + +### 问题 + +- **组件迁移工作量大** + - 140 个组件,已完成 117 个 + - 需要重构 Base 组件和 Web Adapter + +- **版本依赖管理复杂** + - 多个应用依赖同一个包 + - 版本不一致可能导致构建失败 + +- **构建缓存策略优化** + - Turborepo 缓存配置 + - CI/CD 流水线优化 + +::right:: + +### 解决措施 + +- 使用 Turborepo 优化构建流程 +- 制定 Base Component Pattern 规范 +- 渐进式迁移,避免一次性重构 + + + +--- +transition: slide-left +layout: section +--- + +# 五、GUI测试运行情况 + +GUI 测试的实践 + + + +--- +transition: slide-up +--- + +## GUI 测试 + +运行结果:通过 28/30 个测试案例。 + +其中不通过的案例有一定原因是测试背后调用的 Agent 本身不稳定。 + +--- +transition: slide-up +layout: center +--- + +## 待改进方向 + +- 修改部分文本,避免 GUI 测试无法识别 +- 对齐原版需求文档和 GUI 的要求,当前有测试不通过原因是缺少要求的验证字段以及相应的提示 +- 观察到测试框架似乎存在多次尝试失败后判定为PASS的现象,干扰了测试结果的准确性 + +--- +layout: center +--- + +# Q&A + +欢迎提问