整理前文档快照:04.测试策略
这是历史资料,不作为当前操作说明;返回现行页面。原文按文本保存,保留当时方案及验证范围。
text
# 测试策略
## 测试分层
```mermaid
graph TD
E2E[E2E 测试] --> Integration[集成测试]
Integration --> Unit[单元测试]
Unit --> Static[静态检查]
Static --> ESLint[ESLint]
Static --> TSC[TypeScript 类型检查]
Static --> Prettier[Prettier]
```
---
## 静态检查
### 后端
```bash
cd yunstack-backend
pnpm lint # ESLint 检查
pnpm format # Prettier 格式化
npx tsc --noEmit # TypeScript 类型检查
```
### 前端
```bash
cd yunstack-web
pnpm lint:eslint # ESLint
pnpm lint:prettier # Prettier
pnpm lint:stylelint # Stylelint
pnpm type-check # TypeScript
cd yunstack-uniapp
pnpm lint:eslint
pnpm lint:prettier
pnpm lint:stylelint
pnpm type-check
```
---
## 单元测试
### 后端 (Jest)
```bash
cd yunstack-backend
pnpm test # 运行全部测试
pnpm test:watch # 监听模式
pnpm test:cov # 覆盖率报告
```
**编写规范:**
```typescript
// user.service.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { UserService } from './user.service';
describe('UserService', () => {
let service: UserService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UserService],
}).compile();
service = module.get<UserService>(UserService);
});
describe('findAll', () => {
it('should return paginated users', async () => {
const result = await service.findAll({ pageNum: 1, pageSize: 10 });
expect(result.list).toBeDefined();
expect(result.total).toBeGreaterThanOrEqual(0);
});
});
});
```
### 前端 (待实现)
```bash
cd yunstack-web
# 计划使用 Vitest
pnpm test
pnpm test:cov
```
---
## E2E 测试
### 后端 (Supertest)
```bash
cd yunstack-backend
pnpm test:e2e
```
```typescript
// test/auth.e2e-spec.ts
import * as request from 'supertest';
describe('Auth (e2e)', () => {
it('/api/v1/auth/login (POST)', () => {
return request(app.getHttpServer())
.post('/api/v1/auth/login')
.send({ username: 'admin', password: '123456' })
.expect(201)
.expect(res => {
expect(res.body.code).toBe('00000');
});
});
});
```
---
## 测试覆盖率目标
| 层级 | 目标 | 说明 |
|------|------|------|
| Service 层 | ≥ 80% | 核心业务逻辑 |
| Controller 层 | ≥ 60% | 路由和参数校验 |
| 工具函数 | ≥ 90% | 纯函数易于测试 |
| E2E | 核心流程 | 登录、CRUD、设备通信 |
### 当前生效门槛(2026-09-11)
`package.json` 的 jest 配置中已启用 `coverageThreshold`,强制校验范围如下:
| Glob | 门槛 | 状态 |
|------|------|------|
| `**/modules/**/*.service.ts` | statements / lines ≥ 80% | ✅ 已达标 |
| `**/modules/**/*.controller.ts` | statements / lines ≥ 60% | ✅ 已达标 |
| `**/gateways/**/*.controller.ts` | statements / lines ≥ 60% | ✅ 已达标 |
**未纳入门槛的层级**(基础设施与网关服务,覆盖率仍偏低,需后续单独治理):Influx / Redis / Prisma、Cache / Mail、WebSocket Service。整体覆盖率(statements 57.46% / lines 57.57%)主要受这些层级拉低。
E2E 目前通过 HTTP 层用例执行:`pnpm test:e2e` → 7 套件 / 55 用例全部通过。
---
## 关键测试场景
### 后端必须测试
1. **认证流程**:登录成功/失败、Token 刷新、登出
2. **权限控制**:admin/普通用户访问权限边界
3. **CRUD 操作**:创建、查询、更新、删除的正确性
4. **参数校验**:必填字段、类型校验、边界值
5. **MQTT 消息处理**:消息解析、Topic 匹配
### 前端必须测试
1. **登录流程**:表单验证、Token 存储、路由跳转
2. **权限路由**:角色路由过滤
3. **列表页面**:分页、搜索、排序
---
## CI/CD 集成
```yaml
# 未来 GitHub Actions 参考
- name: Lint
run: pnpm lint
- name: Type Check
run: pnpm type-check
- name: Unit Test
run: pnpm test:cov
- name: Build
run: pnpm build
```