# 自动化测试指南 本项目包含完整的自动化测试套件,包括单元测试和端到端(E2E)测试。 ## 📁 测试文件结构 ``` backend/services/identity-service/ ├── src/ │ ├── domain/ │ │ └── value-objects/ │ │ ├── mnemonic.vo.spec.ts # 助记词单元测试 │ │ └── phone-number.vo.spec.ts # 手机号单元测试 │ └── infrastructure/ │ └── external/ │ └── blockchain/ │ └── wallet-generator.service.spec.ts # 钱包生成服务测试 └── test/ ├── app.e2e-spec.ts # 完整的 E2E 测试套件 └── jest-e2e.json # E2E 测试配置 ``` ## 🧪 测试类型 ### 1. 单元测试(Unit Tests) 测试单个组件、类或函数的功能。 **位置**: 与源代码文件同目录,文件名以 `.spec.ts` 结尾 **已包含的单元测试**: - ✅ `mnemonic.vo.spec.ts` - 助记词值对象测试 - ✅ `phone-number.vo.spec.ts` - 手机号值对象测试 - ✅ `wallet-generator.service.spec.ts` - 钱包生成服务测试 - ✅ `user-account.aggregate.spec.ts` - 用户账户聚合根测试(已存在) ### 2. 端到端测试(E2E Tests) 测试完整的用户场景和 API 端点。 **位置**: `test/` 目录 **已包含的 E2E 测试**: - ✅ `app.e2e-spec.ts` - 完整的 API 测试套件(8个测试场景,40+测试用例) ## 🚀 运行测试 ### 运行所有单元测试 ```bash npm test ``` ### 运行单元测试(监听模式) ```bash npm run test:watch ``` ### 运行单元测试并生成覆盖率报告 ```bash npm run test:cov ``` ### 运行 E2E 测试 ```bash npm run test:e2e ``` ### 运行特定测试文件 ```bash # 运行助记词测试 npm test -- mnemonic.vo.spec # 运行钱包生成服务测试 npm test -- wallet-generator.service.spec # 运行手机号测试 npm test -- phone-number.vo.spec ``` ### 调试测试 ```bash npm run test:debug ``` 然后在 Chrome 中打开 `chrome://inspect` ## 📊 E2E 测试覆盖的场景 ### 场景 1: 用户注册和账户创建 - ✅ 自动创建账户 - ✅ 验证钱包地址格式 - ✅ 参数验证 ### 场景 2: 用户资料管理 - ✅ 获取个人资料 - ✅ 更新个人资料 - ✅ 认证验证 ### 场景 3: 设备管理 - ✅ 获取设备列表 - ✅ 添加新设备 - ✅ 移除设备 - ✅ 设备数量限制(最多5个) ### 场景 4: Token 管理 - ✅ 刷新 Token - ✅ Token 验证 - ✅ 无效 Token 拒绝 ### 场景 5: 推荐系统 - ✅ 根据推荐码查询用户 - ✅ 使用推荐码注册 ### 场景 6: KYC 认证 - ✅ 提交 KYC - ✅ 身份证号验证 ### 场景 7: 助记词恢复 - ✅ 正确助记词恢复 - ✅ 错误助记词拒绝 - ✅ 账户序列号验证 ### 场景 8: 数据验证 - ✅ 手机号格式验证 - ✅ 各种边界条件测试 ## 🎯 单元测试覆盖的功能 ### Mnemonic 值对象测试 - ✅ 生成 12 个单词助记词 - ✅ 转换为 seed - ✅ 验证助记词格式 - ✅ 助记词相等性比较 - ✅ 拒绝无效助记词 ### PhoneNumber 值对象测试 - ✅ 验证有效的中国手机号 - ✅ 拒绝无效格式 - ✅ 手机号掩码(138****8000) - ✅ 手机号相等性比较 ### WalletGenerator 服务测试 - ✅ 生成完整钱包系统 - ✅ 三条链地址生成(KAVA/DST/BSC) - ✅ 地址格式验证 - ✅ 助记词恢复 - ✅ 助记词验证 - ✅ 加密和解密 - ✅ 密钥派生 ## 📈 查看测试覆盖率 运行覆盖率测试: ```bash npm run test:cov ``` 覆盖率报告会生成在 `coverage/` 目录: ```bash # 在浏览器中查看 HTML 报告 open coverage/lcov-report/index.html # macOS start coverage/lcov-report/index.html # Windows ``` ## 🔧 测试配置 ### 单元测试配置 (package.json) ```json { "jest": { "moduleFileExtensions": ["js", "json", "ts"], "rootDir": "src", "testRegex": ".*\\.spec\\.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" }, "moduleNameMapper": { "^@/(.*)$": "/$1" } } } ``` ### E2E 测试配置 (test/jest-e2e.json) ```json { "moduleFileExtensions": ["js", "json", "ts"], "rootDir": ".", "testEnvironment": "node", "testRegex": ".e2e-spec.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" } } ``` ## 🧩 编写新的测试 ### 添加单元测试 在源文件同目录创建 `.spec.ts` 文件: ```typescript // src/domain/value-objects/my-value.vo.spec.ts import { MyValue } from './my-value.vo'; describe('MyValue', () => { describe('create', () => { it('should create valid value', () => { const value = MyValue.create('test'); expect(value).toBeDefined(); }); }); }); ``` ### 添加 E2E 测试 在 `test/` 目录添加新的测试场景: ```typescript // test/new-feature.e2e-spec.ts import { Test, TestingModule } from '@nestjs/testing'; import { INestApplication } from '@nestjs/common'; import * as request from 'supertest'; import { AppModule } from '@/app.module'; describe('New Feature E2E Tests', () => { let app: INestApplication; beforeAll(async () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleFixture.createNestApplication(); await app.init(); }); afterAll(async () => { await app.close(); }); it('should test new feature', async () => { const response = await request(app.getHttpServer()) .get('/api/v1/new-endpoint') .expect(200); expect(response.body).toBeDefined(); }); }); ``` ## 🎬 CI/CD 集成 ### GitHub Actions 示例 创建 `.github/workflows/test.yml`: ```yaml name: Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest services: postgres: image: postgres:16 env: POSTGRES_PASSWORD: postgres options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '20' - name: Install dependencies run: npm ci - name: Generate Prisma Client run: npm run prisma:generate - name: Run unit tests run: npm test - name: Run E2E tests run: npm run test:e2e env: DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test - name: Upload coverage uses: codecov/codecov-action@v3 ``` ## 📋 测试最佳实践 ### 1. 测试命名 使用清晰的描述性名称: ```typescript // ✅ 好的命名 it('应该拒绝无效的手机号格式', () => {}); // ❌ 不好的命名 it('test1', () => {}); ``` ### 2. AAA 模式 遵循 Arrange-Act-Assert 模式: ```typescript it('应该创建用户', () => { // Arrange - 准备测试数据 const userData = { name: 'Test' }; // Act - 执行操作 const user = createUser(userData); // Assert - 验证结果 expect(user.name).toBe('Test'); }); ``` ### 3. 独立性 每个测试应该独立运行: ```typescript // ✅ 好的做法 beforeEach(() => { // 为每个测试准备新的数据 testData = createFreshData(); }); // ❌ 不好的做法 let sharedData; it('test1', () => { sharedData = modify(sharedData); // 影响其他测试 }); ``` ### 4. 清理 在测试后清理资源: ```typescript afterEach(async () => { await cleanupTestData(); }); afterAll(async () => { await app.close(); }); ``` ## 🐛 调试失败的测试 ### 1. 查看详细输出 ```bash npm test -- --verbose ``` ### 2. 运行单个测试 ```bash npm test -- --testNamePattern="应该创建用户" ``` ### 3. 使用 console.log ```typescript it('debug test', () => { const result = someFunction(); console.log('Result:', result); // 调试输出 expect(result).toBe(expected); }); ``` ### 4. 使用 Node 调试器 ```bash npm run test:debug ``` 在 Chrome 打开 `chrome://inspect`,点击 "inspect" ## 📚 相关资源 - [Jest 文档](https://jestjs.io/docs/getting-started) - [NestJS 测试文档](https://docs.nestjs.com/fundamentals/testing) - [Supertest 文档](https://github.com/visionmedia/supertest) - [测试驱动开发 (TDD)](https://martinfowler.com/bliki/TestDrivenDevelopment.html) ## 🎯 测试目标 ### 当前覆盖率目标 - 单元测试覆盖率:> 80% - E2E 测试覆盖率:> 70% - 关键路径覆盖率:100% ### 持续改进 - 为新功能添加测试 - 为 bug 修复添加回归测试 - 定期审查和更新测试 - 移除过时的测试 --- ## 🚀 快速开始 ```bash # 1. 安装依赖 npm install # 2. 安装 supertest(E2E 测试依赖) npm install --save-dev supertest @types/supertest # 3. 运行所有测试 npm test # 4. 运行 E2E 测试 npm run test:e2e # 5. 查看覆盖率 npm run test:cov ``` 祝测试愉快!🎉