单元测试中的FIRST代表下面五组英文单词对应的原则:
- Fast
- Isolated / Independent
- Repeatable
- Self-validating
- Timely / Thorough
软件开发中,往往会因为我们没有注意到的逻辑或难以理解的代码,而引进Bug来。
怎么尽早地发现Bug,软件人一直在做这方面的努力,单元测试是众多努力中相当有成效的一个方式。而写单元测试的过程中有些经验教训呢?这些经验教训背后有没有一些通用性的原则呢?答案是肯定的,FIRST原则就是其中重要的一个。
执行快速(Fast)
单元测试执行一定要快,如果要给一个标准的话,每个单元测试的执行应该是秒级的。这样研发同学可以在项目周期的任意时间点,可以方便地执行单元测试, 即便是有几千个单元测试也不影响。这些单元测试最好在几秒内运行完并返回期望的结果。如果是和时间相关的测试,不应该真的等待时间流逝再看结果,而应该使用 Mock 来模拟时间。
隔离(Isolated)/独立(Independent)
每一个测试用例运行时、准备环境变量时或测试前环境搭建过程中,都是隔离的。过程中,不能有相互依赖,这样最终的测试结果可以不受其它因素的影响。如果需要一些配置,这些配置应该在本单元测试的初始化阶段完成。
可重复(Repeatable)执行
单元测试可以在不做任何修改情况下,在任何环境下执行。如果单元测试不依赖网络或数据库,单元测试失败原因的排查中,就不用考虑这方面的原因,毕竟单元测试依赖的只是被测试类或方法中的代码。这个原则,可以方便地让自己的单元测试逻辑保持良好的价值。
代码测试中自校验(Self-validating)
写了单元测试后,咱们不能再依赖肉眼观察,看被测代码的结果是否正确。测试代码自身会明白无误地告诉咱哪条测试用例失败了。在JUnit中,咱们一般使用assertTrue或assertEquals来验证。
即时(Timely)/完整(Thorough)
按TDD的理念, 应该在相应的业务代码之前定单元测试。这一点上,大家可以自己掌握是否采用TDD的开发理念。不过,这个的理念是,即时地写单元代码,即便是很小的代码也是这样。 如果你不用 TDD,这一条指的是单元测试要达到下面的“完整”标准:
- 覆盖所有基本路径 (Happy Path)
- 边界条件
- 安全问题
- 覆盖所有可能的功能性用例,而不只是应付 100% 代码覆盖率的要求
遵循FIRST原则,单元测试质量会提升很多。不过,也不是说,单单遵循这个FIRST原则后,就包治百病了,毕竟还有其它的一些因素影响着单元测试的质量。基于FIRST原则后, 我们可以有一个良好的基础来构建整体软件系统。