← Backend / 工程实践

03_测试CI与部署

单元到端到端测试、CI 流水线、配置、部署、可观测性与回滚。

测试、CI 与部署

学习目标:把代码从“本地可运行”推进到“可重复验证、可观察、可回滚”。

1. 测试按风险分层

层次 验证重点 典型速度
单元测试 业务规则、边界值 快
集成测试 数据库、缓存、外部适配层 中
契约/API 测试 状态码、字段、权限 中
端到端测试 关键用户流程 慢

不要只追求覆盖率数字。优先测试最贵的失败:重复创建、越权、事务部分成功、迁移不兼容和服务重启后的数据保留。前端与后端应共用一份 API 契约;接口变化先检查双端兼容性。

2. 最小 CI 流水线

拉取代码 → 安装固定版本依赖 → 格式/静态检查 → 单元测试
         → 数据库集成测试 → 构建产物 → 安全扫描 → 发布候选

CI 运行在干净环境,不能依赖本机缓存或未提交配置。测试密钥与生产密钥分离;不要在日志输出凭证。构建产物应可追溯到提交与依赖版本。

3. 配置、部署与回滚

配置与代码分离:数据库 URL、密钥、外部服务地址由环境或密钥管理提供。部署前备份与迁移数据库;应用先兼容旧表结构,避免滚动发布时新旧实例互相破坏。发布失败时能恢复上一个应用版本,数据库回滚往往更难,应提前设计兼容迁移。

容器镜像应尽量小、固定基础镜像版本、使用非 root 用户并只包含运行所需文件。反向代理或平台层提供 TLS;服务设置健康检查、资源限制和优雅退出。

4. 可观测性与故障排查

  • 日志:结构化记录请求 ID、错误类型与必要上下文,不记录密钥和完整敏感数据。
  • 指标:请求量、错误率、延迟分位数、数据库连接池、队列积压。
  • 追踪:跨前端、API、数据库或外部服务定位慢调用。
  • 告警:针对用户可感知的问题和持续异常,而非每条日志都报警。
易错点:健康检查全绿也不代表业务成功。发布后还应观察关键操作的成功率、耗时和真实用户错误。

自测

  1. 为什么数据库迁移要考虑新旧应用短时间共存?滚动发布时两种版本可能同时处理请求。
  2. CI 测试通过是否等于线上一定没问题?不等于,还需发布观察、告警与回滚方案。

5. 让每一层测试承担不同证据

单元测试验证标题规范化、权限判定、版本冲突等纯规则;数据库集成测试验证约束、事务和迁移;API 测试验证请求解析、状态码和错误结构;端到端测试验证浏览器登录、创建、刷新后仍可见。不要让所有测试依赖同一个真实外部服务,否则失败难定位且运行慢。

为笔记服务建立一张验收表:正常创建、空标题、同键重复提交、用户 A 读用户 B 数据、版本冲突、数据库不可用。每个场景至少有一层直接验证,越权和事务回滚需要真实边界的测试,不能只 mock 掉。

6. CI 的可复现标准

每个作业从声明的运行时版本和锁定依赖开始,明确数据库服务、迁移命令与测试命令。缓存只能加速,清掉缓存后仍应通过。构建产物标记提交 ID;若测试与构建使用不同依赖版本,测试通过并不能证明发布产物可靠。

检查格式与类型 → 单元测试 → 启动测试数据库并迁移
→ API/集成测试 → 前端构建与组件测试 → 关键 E2E
→ 生成可追溯产物 → 人工或自动发布门禁

7. 发布后验证与回滚演练

发布前记录当前版本、备份状态、迁移脚本和回滚方式;发布后用真实健康检查和一条只用测试账户的关键流程验证。观察错误率、P95 延迟、数据库连接池和前端请求失败率。若异常超阈值,先回滚应用版本,再评估数据库数据是否需要修复;破坏性迁移往往无法简单回滚,应采用先兼容、后切换、最后清理的顺序。

练习:故意让新版本读取不存在的字段,验证 CI 或预发能否发现;再演练恢复旧应用,同时说明为什么旧应用仍应兼容迁移后的表结构。