说起软件测试四个字,想必大家脑海中浮现的有集成测试、系统测试、黑盒测试、白盒测试等,可能就是没想到会有单元测试。 对于大学是学习软件工程专业出身的同学来说可能会听过这四个字,对工作好几年的职场老鸟可能也听过但是没实际用过居多。绝大多数的开发人员都是忙于把手头的工作开发好,并不会把单元测试纳入工作范畴,他们会说,我连功能开发都忙不过来了,哪有时间去做单元测试,况且还要写测试代码,那不是重复写一篇代码功能吗?但,单元测试真的不值得花时间去做吗,那是因为可能你并不清楚单元测试的投入产出比有多高,下面就简单介绍单元测试到底能给开发人员带来多少好处。
单元测试本质上也是代码,与普通代码的区别在于它是验证代码正确性的代码。可简单做个定义:单元测试是开发人员编写的、用于检测在特定条件下目标代码正确性的代码。
软件开发天生就具有复杂性,没人敢打包票说自己写的代码一点问题都没有,或者不经测试就能保证代码正确运行,可能你在这个执行路径下能够执行,殊不知还有其他路径,有一一去验证过吗,因此,要保证程序的正确性就必须要对我们代码进行严格测试。
举个简单例子:比如有个计算类,里面有个 add 方法,操作就是两个数进行相加。
public class Calculator {
public int add(int one, int another) {
//只是简单的两个数相加
return one + another;
}
}
常规做法:假如你写好了这个方法,你想进行验证 add 方法的正确性,需要写个使用 add 方法的 main 函数,首先实例化 Calculator 类,然后调用 add 方法并传入两个参数,比如 1 和 2。然后你运行这个工程,看得出结果是否为 3 ,如果是 3 ,则表明我这个方法写的没有错误,可能就不测试了,就继续开发后续的功能,如果不是 3 ,则返回去看看代码中哪里出错了,重新进行调试,甚至有时候肉眼还看不出代码哪里出错,此时就引入断点去查看,在此期间,很大一部分时间就花在断点、调试、运行上。
单元测试做法:首先会利用 JUnit 测试框架(至于这个框架后面介绍)写一段测试代码,如下:
public class CalculatorTest {
public void testAdd() throws Exception {
Calculator calculator = new Calculator();
int sum = calculator.add(1, 2);
Assert.assertEquals(3, sum);
}
}
这里的 CalculatorTest 是 Calculator 对应的测试类,这里的 testAdd 对应着 add 的测试方法,进行测试一般分为三步骤:
看到 Assert 这个关键词了吗,这里可以理解为断言或者期望值,根据入参的值,期望有个什么值输出,而不是靠肉眼去验证是不是自己想要的值,是直接通过判断值是否相等性来验证会具有更客观性。
以上介绍的只是单元测试一点点,那它能给我们带来哪些更多好处呢?
通常我们在做任何工作会先考虑它的回报,编写代码更是如此。如果单元测试的作用不大,没有人会愿意再写一堆无用的代码,那么单元测试到底能够给我们带来什么优点呢?如下:
等等,讲了这么多优点,无非就是良好的接口设计、正确性、可回归、可测试、完善的调用文档、高内聚、低耦合,这些优点已经足以让我们对单元测试重视起来了,但是个人觉得还有更重要的原因。
很多开发人员不写单元测试,最重要的一个原因是他们并不知道单元测试能够带来什么好处,甚至根本不了解单元测试这个词,那自然就像平行线般与之毫无交集。还有一个比较重要的原因是一些开发人员的编程思想还处在一个相对初级的阶段,开发软件只管实现功能,什么高内聚、低耦合、重构、设计、可测试等认为太过专业,对于这些名词以及意义还不了解,这自然不会考虑使用了。还有一些非思想层面的理由,如下:
JUnit 是一个 Java 语言的单元测试框架,它是 xUnit 单元测试架构体系的一个实例,用于编写和运行可重复的测试。它包括以下特性:
TestNG 是一个测试框架,其灵感来自 JUnit 和 NUnit ,但引入了一些新的功能,使其功能更强大,使用更方便。TestNG 消除了大部分的旧框架的限制,使开发人员能够编写更加灵活和强大的测试。 因为它在很大程度上借鉴了Java注解( JDK5.0 引入的)来定义测试,它也可以显示如何使用这个新功能在真实的Java语言生产环境中。
特点如下:
因为 JUnit 测试框架是基于 Java 语言,当然 Android 开发也是基于 Java 语言,所以在 Android 中我们可以用 Junit4 单元测试框架进行回归测试,但同时,Google 也提供了一个 AndroidJUnit4 测试框架,看名字就知道它是基于 JUnit 4 框架适合在 Android 环境中做单元测试。
那么,AndroidJUnit4 和 Junit4 有什么区别呢?很大一个区别在于:
1,AndroidJUnit4 测试可以在真机的环境下进行。比如你要测文件读取SD卡,或者操作 SqlLite 数据库,这些条件只有在真机上才有的,此时你用 AndroidJUnit4 框架测试,可以直接跑起来用真实的环境做相应的单元测试。
2,JUnit4 测试是运行在工程项目中,也就是在编译阶段。此时如果想要模拟 Android 环境,比如我想用 JUnit4 来测试 Activity 类,那么就需要引用第三方库来支持,引用 Mockito 和 Robolectric 框架来模拟 Android 环境进行相应的单元测试。
所以何时用 AndroidJUnit4 和 JUnit4 不同的框架进行单元测试,就看你待测试的方法前置条件是什么,然后做不同的选择。
总的来说,单元测试不是集成测试,单元测试只是测试一个方法单元,不是测试一整个流程。集成测试是一种End To End的系统测试,测试相关模块集成在一起是否能够按照预期工作,一般都是接口或者功能层面的测试,可能会依赖很多系统因素,测试的代码逻辑一般比较复杂,运行时间会比较长,出错之后的修复成本高。单元测试则是开发者在集成测试之前就已经进行自测过,同时呢,进行单元测试之后,对于某个方法的执行路径组合进行了一一验证,它只关注三个目标:
源于对掌握的Android开发基础点进行整理,罗列下已经总结的文章,从中可以看到技术积累的过程。
1,Android系统简介
2,ProGuard代码混淆
3,讲讲Handler+Looper+MessageQueue关系
4,Android图片加载库理解
5,谈谈Android运行时权限理解
6,EventBus初理解
7,Android 常见工具类
8,对于Fragment的一些理解
9,Android 四大组件之 " Activity "
10,Android 四大组件之" Service "
11,Android 四大组件之“ BroadcastReceiver "
12,Android 四大组件之" ContentProvider "
13,讲讲 Android 事件拦截机制
14,Android 动画的理解
15,Android 生命周期和启动模式
16,Android IPC 机制
17,View 的事件体系
18,View 的工作原理
19,理解 Window 和 WindowManager
20,Activity 启动过程分析
21,Service 启动过程分析
22,Android 性能优化
23,Android 消息机制
24,Android Bitmap相关
25,Android 线程和线程池
26,Android 中的 Drawable 和动画
27,RecylerView 中的装饰者模式
28,Android 触摸事件机制
29,Android 事件机制应用
30,Cordova 框架的一些理解
31,有关 Android 插件化思考
32,开发人员必备技能——单元测试