测试关键点
1. 测试的是“行为”不是“实现细节”
- ✅ 测试应该验证功能是否正确,而不是代码怎么写的。
- ❌ 不要因为内部重构就需要改一堆测试。
✅ 比如测试输出正确,不关心你用的算法是循环还是递归。
2. 单元测试要小、快、独立
- 小:每个测试验证一个明确的点。
- 快:运行速度快,支持频繁运行。
- 独立:每个测试都可以独立运行,互不依赖。
3. 测试命名清晰,能表达意图
一个好测试名就像一句人话说明了功能点和预期:
TEST(ShoppingCartTest, AddingSingleItemIncreasesItemCountByOne)
可读性 > 技巧。
4. 使用断言清晰表达期望
如:EXPECT_EQ(price, 100)
不要仅输出调试信息,而要用断言验证,否则不能自动发现错误。
5. 保持测试代码的可维护性
测试代码也是“产品代码”,要注意:
- 不要重复
- 明确 Setup
- 抽象公共逻辑到
TestFixture
- 避免测试之间相互依赖
6. 不要滥用 Mock / Stub
- 使用 mock 要有理由,不要“为 mock 而 mock”
- 只 mock“你不控制的依赖项”,比如数据库、网络、外部服务
7. 覆盖典型路径 + 边界 + 异常情况
确保你测试了:
类型 | 示例 |
---|---|
正常情况 | add(2, 3) 返回 5 |
边界情况 | 空输入、最大值、负数 |
异常情况 | 输入错误,是否抛出异常? |
特殊行为 | 幂等性、重复操作是否一致 |
8. 遇 bug 要写“回归测试”
发现一个 bug → 先写测试重现它
修复后 → 测试变绿,避免以后再犯
9. 集成测试 + 单元测试结合使用
- 单元测试:验证一个类/函数的行为
- 集成测试:验证模块之间协作是否正确
- 端到端测试(E2E):模拟用户真实操作验证整个系统
10. 失败信息要清楚,便于排查
不然你运行测试看到:
Expected: true, Actual: false
这很难定位问题。可以这样写:
EXPECT_EQ(cart.getItemCount(), 1) << "Item count should be 1 after adding 1 item";
总结:写好测试的黄金法则
法则 | 说明 |
---|---|
独立 | 每个测试可以单独运行 |
快速 | 跑得快,能频繁运行 |
可读 | 测试名和内容能一眼看懂 |
覆盖全面 | 正常 + 异常 + 边界 |
验证行为而非实现 | 不跟着内部结构改 |
及时更新和修复 | 发现问题先补测试,再修代码 |
加入 CI/CD 流水线中 | 保证代码提交/发布前都通过所有测试 |