C/C++单元测试理论精要(六)
2.1 可测性问题详解(2)
接下来我们讨论重点问题:覆盖输入。一个函数,输入会有哪些呢?输入包括两方面:外部输入,内部输入。外部输入容易理解,就是函数外部可以设定的输入,包括参数,全局变量,成员变量。
关键是内部输入。因为很少有文献讨论内部输入,对很多人来说,内部输入可能是一个陌生的词,我们首先来看看内部输入是什么。一个函数,对于调用底层函数获得的数据,是如何处理的呢?跟参数一样,也是分类处理。所以,测试时也要分类检测,这与参数没什么区别。这就是内部输入。
内部输入有几种情形?一共有六种:自然输入、不可控、失真、难于初始化、静态输入,中断输入。
自然输入
自然输入就是调用底层函数的实际代码,获得自然的计算结果。底层函数必须存在,可控,并且正确。对于自然输入,测试时并不是什么也不用做。为了检测程序是否对底层函数的各种可能输出做合适的判断和处理,需要让底层函数输出合适的数据,这就要通过设置合适的参数等数据来间接控制底层函数的输出。有时候,这个工作是很困难的,这就是难以初始化,后面有专门介绍。
不可控
底层函数还是调用实际代码,但是底层函数的输出不符合测试需求。在这个例子中,底层函数的功能是取得环境温度,我们要检测程序是否对各种环境温度做了合适的处理,但是真实的环境温度不可能实时大幅变化,这就是不可控。不可控在单元测试当中是相当常见的,例如底层函数返回一个随机数、也是不可控,底层函数是用来连接网络的,可能无法控制它的各种状态,这些都是不可控。
失真
底层函数调用的是桩代码。桩代码当然不能实现原有代码的功能,这就是失真。这个例子跟介绍不可控是同一个函数,不同的是,底层函数调用的是桩代码,一般的桩代码是什么也不做的,底层函数的返回值总是0,并且未输出环境温度,测试做不下去。失真是打桩造成的,是打桩的必然结果。可不可以通过修改桩代码来解决失真呢?有时候是可以的,有时候不行,后面会有进一步的介绍。
刚才我们讨论了失真。
难于初始化
&n
相关文档:
googletest C/C++ 测试框架非常好用,介绍及下载请看 http://code.google.com/p/googletest/
//============================================================================
// 使用 googletest 测试框架
//============================================================================
// Returns n! ......
#include <stdio.h>
#define bits(p, d) { \
int _tmp=p->d, _bits=0; \
for (p->d=1; p->d; p->d<<=1) \
_bits++; \
p->d=_tmp; \
printf("%s->%s has %d bits", #p, #d, _bits); \
}
typedef struct _s{
int a:4;
} S;
int main()
{
S tmp, ......
宏定义了一个代表特定内容的标识符。预处理过程会把源代码中出现的宏标识符替换成宏定义时的值。宏
最常见的用法是定义代表某个值的全局符号。宏的第二种用法是定义带参数的宏,这样的宏可以象函数一样
被调用,但它是在调用语句处展开宏,并用调用时的实际参数来代替定义中的形式参数。
1.#define指令
#define预处理 ......