1,什么是单元测试
单元测试是应用测试策略中的基本测试。用于实现对软件中的最小可测试单元进行检查和验证。
通过针对代码创建和运行单元测试,可以轻松验证各个单元的逻辑是否正确。在每次构建后运行单元测试可帮助我们快速捕捉和修复由应用的代码更改导致的软件回归。
针对Android项目,往往也需要除黑盒测试外更加可靠的质量保障,这正是单元测试的用武之地。单元测试周期性对项目进行函数级别的测试,在良好的覆盖率下,能够持续维护代码逻辑,从而支持项目从容应对快速的版本更新。
单元测试通常以可重复的方式运用尽可能小的代码单元(可能是方法、类或组件)的功能。当您需要验证应用中特定代码的逻辑时,应构建单元测试。例如,如果您正在对某个类进行单元测试,则测试可能会检查该类是否处于正确状态。通常,代码单元在隔离的环境中进行测试;您的测试仅影响和监控对该单元的更改。
2,单元测试收益
不仅仅用来保证当前代码的正确性,更重要的是用来保证代码修复、改进或重构之后的正确性
1,提高稳定性,能够明确地了解是否正确的完成开发
2,快速反馈bug,跑一遍单元测试用例,定位bug
3,在开发周期中尽早通过单元测试检查bug,最小化技术债
4,为代码重构提供安全保障,在优化代码时不用担心回归问题,更加易于维护。
5,对代码解耦提供约束, 如果代码依赖很复杂, 说明耦合度高, 如果存在这样的类, 通常是很难写出单元测试的
3、单元测试原则
FAST: - 快速:测试必须非常快,这样开发人员可以对每一个小更改运行测试,而不用中断思绪去等待测试运行。
INDEPENDENT: - 隔离:不同的测试用例之间是隔离的。一个测试不会依赖另一个测试。不同测试的故障是相互隔离的。
REPEATABLE: - 可重复:测试是可重复的;可重复意味着可以自动化。在循环运行时,测试总能给出相同的结果。
SLEF-VALIDATING: - 自我验证:测试可以验证它们的结果,当它们全部通过时,给出一个简单的“OK”报告,当它们失败时,描述简明的细节。
TIMELY: 及时 - 及时:测试是及时的。程序员在代码上线前,及时地编写它们,以防止bug。
单元测试不是越多越好,而是越有效越好!以下代码建议覆盖单元测试:
-
逻辑复杂的
-
容易出错的
-
不易理解的,即使是自己过段时间也会遗忘的,看不懂自己的代码,单元测试代码有助于理解代码的功能和需求
-
公共代码。比如自定义的所有http请求都会经过的拦截器;工具类等。
-
核心业务代码。一个产品里最核心最有业务价值的代码应该要有较高的单元测试覆盖率。
4,Android单元测试
在Android中,单元测试的本质依旧是验证函数的功能,测试框架也是JUnit。在Java中,编写代码面对的只有类、对象、函数,编写单元测试时可以在测试工程中创建一个对象出来然后执行其函数进行测试,而在Android中,编写代码需要面对的是组件、控件、生命周期、异步任务、消息传递等,虽然本质是SDK主动执行了一些实例的函数,但创建一个Activity并不能让它执行到resume的状态,因此需要JUnit之外的框架支持。
android单元测试类型主要分为两类:
Local tests(本地测试) 即在PC上执行的单元测试。可以直接运行在JVM上运行,速度也更快。
Instrumented tests(仪器化测试) 运行在真机/模拟器(不推荐)上的单元测试用例。
5,常用的单元测试框架
- Junit : 单元测试框架, 一般使用Junit4
- hamcrest : Matcher工具,用来辅助写断言
- mockito : mock框架, 用于创建mock数据等, 对业务依赖进行隔离(例: 对webservice进行mock, 以屏蔽网络对单元测试结果的影响)
- powermock : 在mockito的基础上, 添加了mock静态方法的能力
- mockk: kotlin的mock框架, 在kotlin环境下, 使用mockito等会存在一些bug, 如果使用kotlin写单元测试/或者测试kotlin的代码, 建议使用这个. 注意的是同一个单元测试内, 不能和mockito/powermock一起使用
- Robolectric : 用于在PC上模拟执行Android单元测试的工具