如果你会写代码,那么你就会写单元测试。然而写好单元测试就是另一个话题了。你以为单元测试代码是需要你长期维护、重构和开发的产品级代码?别傻了!
本文旨在提供 3 个十分简单的规则来帮你玩儿转单元测试。每个规则之后都会给你提供可轻易实现的实用技巧。
1.要跑的足够快
写测试的目的就是为了运行他们。主要有两个好处:
- 确保程序正常执行
- 程序异常是查找原因
总体而言,测试是程序的安全保障,是避免回归测试的主要武器。它们使得你可以重构代码而不会引入已经修复的 bug。
然而,需要注意的是:你需要执行它们以使它们正常工作。
每次执行测试,它都会给你一个代码状况的反馈。反馈所用的时间越短,你找到问题的速度就越快,问题也就被修复的越快。也就是说你希望每做一次改动就执行一次测试,而不是在每次发布版本之前或基于每日的基础版本执行测试。
测试执行的越频繁,你从中得到的信息就越多。
你等待测试执行的时间越短,你经常执行它们的意愿就越高。简而言之,如果想要频繁的执行测试,那么测试代码执行的速度就必须要快,快到无可复加!
整个测试执行通过的时间应该限制在 1 秒之内,而不是 10 秒,更不能是 1 分钟。
这意味着你:
- 要在 Java 虚拟机(JVM)上执行测试,而不能是在设备上
- 要只测试独立的业务逻辑单元
- 不要将 UI、数据库和网络测试包含在你的主测试套件中
- 不要在测试中使用 wait/sleep 语句
2. 编写小而专的测试
要始终记得编写测试是为了找出问题。也就是说你需要明确设计测试用例的目的是为了捕获应用中的 bug。
假如应用中有一个 bug,你更喜欢哪种测试结果:
一个 bug -> 多条测试失败
一个 bug -> 只有一条测试失败
当然是第二个!因为这样比较容易调试。当一个测试失败时,你可以根据测试名称来查看哪里出了问题。
@Test
public void logInShouldFailWithWrongPassword() throws Exception {
// Test code
}
每一个 bug 必须只有一个对应的测试失败。失败的原因需要用测试名来描述。
这样会强制你针对每个测试只检查一个点,并且会保持测试足够小而更容易理解,解释和维护。
这也是为什么一个好的测试应该像我们代码库中的其他方法一样,小(只有几行代码)而专(只测一个点)。
要做到这一点,你需要:
- 在每条测试只包含一条断言/验证语句
- 将少量的大测试拆解为大量的小测试
- 在测试名中明确描述失败的原因
3. 100% 的可靠性
测试是程序的安全保障,所以你需要认真对待失败的测试。你需要放下手头所有的事情去解决问题。
想象一下,程序在你急切的想要添加一个新特性时突然出现了问题,而你不得不放下当前工作去修复出现的问题。这是多么令人沮丧的事情啊!!!
再想一下,如果你花费了几个小时的时间去分析问题,没有任何头绪,(绝望中)又执行了一次测试,所有的测试都通过了...
对开发者而言,最沮丧的事情莫过于浪费时间在那些清理一下工程或重启一下 IDE 就被修复的随机错误上。
如果多个测试都是这样的原因导致的,你会对整个测试套件失去信任。你不再认真对待失败的测试,也将不再从整个测试套件中得到任何帮助。
这也是为什么你要保持测试 100% 的可靠性,并且只在真正出现问题时使测试失败。
要做到这一点,你需要:
- 在 JVM 上运行测试(与设备的连接可能会断开)
- 在测试中模拟网络交互
- 将 UI/集成测试移出单元测试套件
总结
测试执行的越频繁,你从中得到的信息就越多。好的单元测试依赖于足够快、专,并且可靠性足够高。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于