1、为什么要写单测?
单测即单元测试(Unit Test),是对软件的基本组成单元进行的测试,比如函数、过程或者类的方法。其意义是:
- 功能自测,发现功能缺陷
- 自我Code Review
- 测试驱动开发
- 促进代码重构并提升代码质量
1.1、代码覆盖率
单测质量最直接表现的指标就是代码覆盖率,分为语句覆盖(Statement coverage)、分支覆盖(Branch coverage)、条件覆盖(Condition converage)、路径覆盖(Path coverage)
1.2、单元测试 VS 集成测试
系统上线前都会做回归测试和集成测试,但为什么还要加单元测试呢?
指标对象 | 单元测试 | 集成测试 |
---|---|---|
测试对象 | 程序单元 | 模块组合 |
测试方法 | 白盒测试 | 黑盒测试 |
测试时间 | 开发阶段 | 集成阶段 |
测试内容 | 代码逻辑 | 接口功能 |
测试粒度 | 较细粒度 | 较粗粒度 |
2、如何写好单测?
2.1、单测规约
可以参考阿里巴巴 的Java开发规范,以下几点在单测中要特别关注:
- 【强制】好的单测必须遵守AIR原则。说明:单元测试在线上运行时,像空气一样感觉不到,但在测试的质量保证上,却是非常关键的。好的单元测试宏观上说,具体有自动化(Automatic)、独立性(Idependent)、可重复执行(Repeatable)的特点。
- 【强制】单元测试应该是全自动执行的,并且非交互式的。测试用例通常是被定期执行的,执行过程必须完全自动化才有意义。输出结果需要人工检查的测试不是一个好的单元测试。单元测试中不准使用System.Out来进行人肉验证,必须使用Assert来验证。
- 【强制】单元测试是可以重复执行的,不能受到外界环境的影响。
- 【推荐】编写单元测试代码遵守BCDE原则,以保证被测试模块的交付质量。
- B: Border,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。
- C: Correct,正确的输入,并得到预期的结果。
- D: Design,与设计文档相结合,来编写单元测试。
- E: Error,强制错误信息输入(如:非法数据、 异常流程、业务允许外等),并得到预期的结果
2.2、一把好工具
写单侧首先要有好的单测工具,常用工具: Mockito、PowerMock、 EasyMock、JMockito等,Mock可以解决:
- 解除对外部服务依赖
- 减少全链路测试的数据准备
- 模拟一些非正常的流程
- 不用加载项目环境配置
- 实现模块之间的并行开发
2.3、编写单元测试
可以把单元测试编写流程分为四大步骤,八大操作。
定义对象阶段
定义测试对象
在编写单元测试时,首先需要定义被测对象,或直接初始化、或通过Spy包装…实例化。
- 直接构建对象
UserService userService = new UserService(); - 利用Mockito.spy方法
UserService userService = Mockito.spy(new UserService());
UserService userService = Mockito.spy(UserService.class); - 利用@Spy注解
@RunWith(PowerMockRunner.class)
public class CompanyServiceTest {
@Spy
private UserService userService = new UserService();
}
- 利用@InjectMocks注解
@RunWith(PowerMockRunner.class