# 测试环境配置指南

本文档说明测试数据清理的自动化策略。

## 🎯 核心策略（极简版）

**集成测试必须使用独立测试数据库，禁止复用开发数据库。**

系统根据 `NODE_ENV`、`ALLOW_TEST_DB_CLEANUP` 与测试数据库连接共同判断是否允许清理数据：

| 条件 | 行为 | 说明 |
|------|------|------|
| `NODE_ENV=test` + `ALLOW_TEST_DB_CLEANUP=true` + `DATABASE_URL` 含 `test/integration` 标识 | ✅ **允许清理** | 仅测试专用数据库可清理 |
| `NODE_ENV=test` 但缺少显式授权 | ❌ **拒绝清理** | 防止误删开发数据 |
| `NODE_ENV=development` | ⚠️ **跳过清理** | 开发环境保留数据 |
| `NODE_ENV=production` | ❌ **禁止清理** | 强保护 |

---

## 📝 使用场景

### 场景1: CI/CD 自动化测试

```bash
# 运行测试（自动拉起 Docker 测试数据库）
npm run test:backend:integration
```

**效果**:
- ✅ 自动使用独立 PostgreSQL 测试库
- ✅ 每次运行前重建 schema 并初始化 seed
- ✅ 清理逻辑只会作用于测试库

---

### 场景2: 本地开发调试

```bash
# 查看测试库数据或手动调试
npm run test:backend:integration
```

**效果**:
- ✅ 测试运行不再污染开发数据库
- ✅ 测试容器可保留用于排查
- 如需删除容器：`npm run test:backend:integration:down`

---

### 场景3: 生产环境（安全保护）

```bash
# 即使手工设置，也会因为不是测试数据库而拒绝清理
NODE_ENV=test ALLOW_TEST_DB_CLEANUP=true DATABASE_URL=postgresql://.../ffws_dev npm run test:backend:integration
# ❌ Error: 当前数据库不是测试库，禁止执行清理!
```

**效果**:
- ❌ 完全禁止清理操作
- ✅ 防止误操作
- ✅ 保护生产数据

---

## 🔄 工作流程

### 测试环境 (NODE_ENV=test)

```
┌─────────────────────────────────────┐
│  测试开始                            │
│  ├─ 生成会话ID: test_xxx_abc       │
│  └─ 创建测试数据（标记会话ID）       │
└─────────────────────────────────────┘
              ↓
┌─────────────────────────────────────┐
│  运行测试                            │
│  └─ 验证功能                         │
└─────────────────────────────────────┘
              ↓
┌─────────────────────────────────────┐
│  测试结束（afterEach）               │
│  ├─ 检测 NODE_ENV=test              │
│  ├─ 检测 ALLOW_TEST_DB_CLEANUP=true │
│  ├─ 检测 DATABASE_URL 是测试库      │
│  ├─ ✅ 自动清理该会话数据            │
│  └─ 输出: 清理完成                   │
└─────────────────────────────────────┘
```

### 开发环境 (NODE_ENV=development)

```
┌─────────────────────────────────────┐
│  测试开始                            │
│  ├─ 生成会话ID: test_xxx_abc       │
│  └─ 创建测试数据                     │
└─────────────────────────────────────┘
              ↓
┌─────────────────────────────────────┐
│  运行测试                            │
│  └─ 验证功能                         │
└─────────────────────────────────────┘
              ↓
┌─────────────────────────────────────┐
│  测试结束（afterEach）               │
│  ├─ 检测 NODE_ENV=development       │
│  ├─ ⚠️  跳过清理，保留数据           │
│  └─ 输出: 跳过清理                   │
└─────────────────────────────────────┘
```

---

## 🔍 判断逻辑

```typescript
function shouldCleanup(): boolean {
  const nodeEnv = process.env.NODE_ENV;
  const allowCleanup = process.env.ALLOW_TEST_DB_CLEANUP;
  
  // 1. 生产环境：严禁清理
  if (nodeEnv === 'production') {
    throw new Error('禁止在生产环境清理数据!');
  }
  
  // 2. 测试环境：自动清理
  if (nodeEnv === 'test') {
    if (allowCleanup !== 'true') {
      throw new Error('测试环境未显式允许清理');
    }
    console.log('✅ 测试环境: 自动清理数据');
    return true;
  }
  
  // 3. 其他环境：跳过清理
  console.log('⚠️  开发环境: 跳过清理，保留数据');
  return false;
}
```

---

## 💡 最佳实践

### ✅ 推荐

1. **统一通过测试脚本运行**
   ```bash
   npm run test:backend:integration
   ```

2. **使用会话隔离**
   ```typescript
   const context = await setupIntegrationTest(app, prisma);
   // 测试...
   await cleanupDatabase(prisma, context.testSessionId);
   ```

3. **测试结束后按需销毁测试库**
   ```bash
   npm run test:backend:integration:down
   ```

4. **开发数据库与测试数据库彻底分离**
   ```bash
   # 开发库走正常 .env
   # 集成测试只走 TEST_DATABASE_URL / Docker 测试库
   ```

### ❌ 避免

1. ❌ 在生产环境运行测试
2. ❌ 在测试环境连接开发/生产数据库
3. ❌ 绕过测试脚本直接执行会触发清理的集成测试

---

## 🚨 安全保护

### 永远不会被清理的数据

1. **开发数据库 / 生产数据库**：因为不是测试库连接，清理会被阻断
2. **内置角色**: `isBuiltIn: true` 的角色
3. **内置权限**: 系统级权限
4. **无会话标记的数据**: 标识字段不包含会话ID的数据

### 生产环境保护

```typescript
// 如果 NODE_ENV=production，任何清理操作都会抛出错误
if (process.env.NODE_ENV === 'production') {
  throw new Error('禁止在生产环境清理数据!');
}
```

---

## 🔧 故障排查

### 问题1: 测试数据没有被清理

**可能原因**: 
- 没有通过测试脚本运行
- `ALLOW_TEST_DB_CLEANUP` 未设置
- 当前数据库连接不含 `test/integration` 标识

**解决方案**:
```bash
# 使用标准脚本
npm run test:backend:integration
```

---

### 问题2: 需要删除测试数据库容器

```bash
npm run test:backend:integration:down
SELECT username, email FROM users WHERE username LIKE '%test_%';

-- 删除特定会话
DELETE FROM users WHERE username LIKE '%test_1703680000000_abc123%';
```

---

### 问题3: 提示"禁止在生产环境清理数据"

**原因**: `NODE_ENV=production`

**解决**:
```bash
# 检查环境变量
echo $NODE_ENV

# 设置正确的环境
export NODE_ENV=development  # 或 test
```

---

## 📊 环境对比表

| 场景 | NODE_ENV | 清理行为 | 适用场景 |
|------|----------|---------|---------|
| **CI/CD** | test | ✅ 自动清理 | 自动化测试 |
| **本地测试** | test | ✅ 自动清理 | 验证功能 |
| **本地开发** | development | ⚠️  跳过清理 | 调试、查看数据 |
| **快速迭代** | 未设置 | ⚠️  跳过清理 | 快速开发 |
| **生产环境** | production | ❌ 禁止清理 | 保护数据 |

---

## 📚 相关文档

- [测试会话隔离机制](./TEST_SESSION_ISOLATION.md) - 精准数据清理策略
- [组织模块测试](./modules/organization/README.md) - 具体测试示例

---

## 🎉 总结

**极简配置，自动判断！**

- ✅ 无需配置环境变量
- ✅ 测试环境自动清理
- ✅ 开发环境保留数据
- ✅ 生产环境完全保护

只需设置 `NODE_ENV`，一切自动完成！

---

**最后更新**: 2025-12-27  
**版本**: v2.3.0 (极简自动化版)
