测试哪些内容

乍看一个方法或者类,是很难找出所有可能出问题的地方的。下面介绍6个值得测试的具体部位,统称为 Right-BICEP,它可以指导一般哪些方面需要被测试,使代码更鲁棒:
Right —— 结果是否正确
B —— 是否所有的边界条件都是正确的
I —— 检查反向关联
C —— 用其他手段交叉检查一下结果
E —— 是否可以强制错误条件发生
P —— 是否满足性能需求

结果是否正确

1,对于测试而言,首要的最明显的任务就是查看所期望的结果是否正确 —— 即验证结果
2,“正确”的定义可能会不断在变,但是无论如何你需要确定代码所作的和你的期望是一致的
3,测试数据比代码更有可能是错的

边界条件

找边界条件是做单元测试最有价值的工作之一,因为bug一般就出现在边界上,需要被考虑的条件有:
1,完全伪造的或者不一致的输入数据,例如一个名为”!!.@”的文件
2,格式错误的数据,例如一个邮件地址”wtli@gmail”
3,空值或者不完整的值,例如null和(0,1,2,)
4,一些与意料中的合理值相去甚远的数值,例如800里开外一枪打爆鬼子的脑袋
5,传入数值与实际要求不符,例如给int型的list传入string型数据
6,数据的顺序与实际要求不符,例如要求是有序的list但传入了无序的数据
7,事情的执行顺序是错误的,例如在登录系统之前就打印了文件
8,…
一个帮助想到可能的边界条件的办法就是助记短语CORRECT
C onformance(一致性)—— 值是否和预期的一致
O rdering(顺序性)—— 值是否如预期那样,是有序或者无序的
R ange(区间性)—— 值是否位于合理的最大最小值之间
R eference(依赖性)—— 代码是否引用了不在代码本身控制范围内的外部资源
E xistence(存在性)—— 值是否存在(例如,是否是非空,非0,在一个集合中等等)
C ardinatity(基数性)—— 是否恰好有足够的值
T ime(相对或绝对的时间性)—— 所有事情的发生是否是有序的?是否在正确的时刻?是否恰好及时?

检查反向关联

1,对于一些方法,可以使用反向的逻辑来验证他们,比如可以通过对结果进行平方的方法来检查一个计算平方根的函数,看测试结果是否和原数据很接近。

1
2
3
4
public void testSquare(){
double x = mySquare(4.0);
assertEquals(4.0,x*x,0.0001);
}

2,当然,一些bug可能会被在两个函数中都出现的错误所掩盖,在可能的情况下,应该尽量使用不同的原理来编写反向测试。

使用其他手段来实现交叉检查

通常计算一个量会有一种以上的算法,在测试中可以用产品中使用的算法之外的算法来交叉测试结果,同样以平方根为例

1
2
3
4
5
6
public void testSquare(){
double num = 4.0;
double root1 = mySquare(num);
double root2 = Math.sqrt(num);
assertEquals(root1,root2,0.0001);
}

强制产生错误条件

在真实的世界中,错误总是会发生:磁盘会慢,网络连接会断开等等。所以在测试程序的时候,应该能够通过强制引发错误,来测试代码是如何处理所有这些真是世界中的问题的。
事实上搞一个无效参数之类的很简单,但是要不拔网线模拟网络错误就需要借助特殊技术了。在下一章就将讨论借助mock来模拟情况发生的方法。
下面列举一些常见的场景因素:
1,内存耗光,
2,磁盘用完
3,时钟出问题
4,网络有问题
5,系统过载
6,显示分辨率太高或太低

性能特性

检查性能特性的好处就是在你发布新版本的时候不会比上一版差很多,但是具体的测试方法就要依具体情况而定,没什么好的指导方案。

下一章单元测试整理(五)—— Mock篇将介绍使用mock对象来模拟一个难以实现的条件或者类来进行单元测试。