我的 CI/CD 流水线通过了 3 个月——直到我查看了日志
看到绿色的勾选标记感觉很棒。每一个 pull request 都通过了。每一次部署都成功了。
接着,一名用户报告了一个功能故障。它已经坏了好几周了。
我打开了流水线日志。我们那些显示“通过”的构建在欺骗我们。
我们的流程看起来很完美:
- Linting
- 单元测试 (Unit tests)
- 集成测试 (Integration tests)
- 构建 (Build)
- 部署 (Deploy)
几个月来,每一步的成功率都是 100%。
点击导出按钮时没有任何反应。没有出现任何错误。我将其追溯到 11 周前的一次变更。流水线通过了。代码审查 (code review) 也通过了。但该功能从一开始就是坏的。
问题不在于我们的代码,而在于我们的测试代码。
我们的集成测试对所有内容都使用了 mock。我们 mock 了整个导出服务。测试检查的是 mock 对象,而不是真实的代码。mock 总是返回成功状态。
我们陷入了“过度 mock”的陷阱:
- 单元测试:为了隔离单元而 mock 一切。这没问题。
- 集成测试:为了速度而 mock 一切。这是一个错误。
- E2E 测试:漏掉了这个特定的流程。
我们的集成测试只不过是昂贵的单元测试。它们验证了我们的 mock 是否工作,而不是验证我们的代码是否工作。
我做了三项改动来修复这个问题:
将 mock 限制在单元测试中。集成测试必须访问真实的数据库、API 和文件系统。如果测试运行缓慢,不要用 mock 来掩盖它。要把这种速度作为优化的信号。
增加契约测试 (contract tests)。这些测试可以确保你的 mock 与真实服务的行为一致。如果 mock 返回了真实服务不会返回的数据,契约测试就会失败。
追踪真实的覆盖率。我们不再只看简单的通过率,而是看测试实际执行了哪些内容。我们的覆盖率从 94% 降到了 67%。这是我们拥有的最诚实的指标。
流水线显示绿色并不意味着你的代码可以正常工作。它只意味着你的测试通过了。这两者是不同的。
最危险的 Bug 是那些流水线认为没问题的 Bug。
问问你自己这些问题:
- 我的测试是在捕捉 Bug,还是仅仅在确认 mock 是否工作?
- 我的集成测试真的实现了“集成”吗?
- 如果我移除所有的 mock,还有多少测试能通过?
- 我衡量的是覆盖率,还是信心?
一个永不失败的流水线是不可靠的。它根本没有经过测试。
来源:https://dev.to/kollittle/my-cicd-pipeline-passed-for-3-months-then-i-read-the-logs-4mbj
