main(argc, argv) /* line 1 */ int argc; /* line 2 */ char *argv[]; /* line 3 */ { /* line 4 */ int c=0; /* line 5 */ /* line 6 */ if(atoi(argv[1]) < 3){ /* line 7 */ printf("Got less than 3\n"); /* line 8 */ if(atoi(argv[2]) > 5) /* line 9 */ c = 2; /* line 10 */ } /* line 11 */ else /* line 12 */ printf("Got more than 3\n"); /* line 13 */ exit(0); /* line 14 */ } /* line 15 */ 例1:程序test1.c
这个简单的程序读取输入的参数,并打印出相关的信息。现在假定用一个测试方案来测试此程序:
Test Case 1: input 2 4 output Got less than 3 Test Case 2: input 4 4 output Got more than 3 Test Case 3: input 4 6 output Got more than 3 Test Case 4: input 2 6 output Got less than 3 Test Case 5: input 4 output Got more than 3 这个测试方案在业界是有一定代表性的,它进行正则测试,表示它将测试对所有正确的输入,程序是否有正确的输出,而忽视非法的输入。程序test1完全通过测试,但它也许隐藏着严重的错误。
现在,对程序进行"变体",用以下简单的改变:
Mutant 1: change line 9 to the form if(atoi(argv[2]) <= 5) Mutant 2: change line 7 to the form if(atoi(argv[1]) >= 3) Mutant 3: change line 5 to the form int c=3; 如果在测试方案中运行此修改后的程序,Mutants 1和3完全通过测试,而Mutant 2则无法通过。
Mutants 1和3没有改变程序的输出,所以是同等变体,而测试方案没有检测到它们。Mutant 2不是同等变体,故Test Cases 1-4将会检测到程序的错误输出,而Test Case 5在不同的电脑上可能会有不同的表现。以上表明,程序的错误输出,可看作是程序可能会崩溃的一个信号。
再回到Mutant 2,在Test Case 5中运行它,如果程序崩溃了,那这个变体测试不但计量到了测试方案的质量,还检测到了严重的错误,这就是变体测试发现错误的方法。
main(argc, argv) /* line 1 */ int argc; /* line 2 */ char *argv[]; /* line 3 */ { /* line 4 */ int c=0; /* line 5 */ int a, b; /* line 6 */ /* line 7 */ a = atoi(argv[1]); /* line 8 */ b = atoi(argv[2]); /* line 9 */ if(a < 3){ /* line 10 */ printf("Got less than 3\n"); /* line 12 */ if(b > 5) /* line 13 */ c = 2; /* line 14 */ } /* line 15 */ else /* line 16 */ printf("Got more than 3\n"); /* line 17 */ exit(0); /* line 18 */ } /* line 19 */ 例2:同等变体
在例2中的同等变体(Mutant 4),它和前一个变体的不同之处在于,Mutant 4是同等变体,这意味着它在构建时的目的,就是要使修改后的程序如同原始程序一样运行。如果在测试方案中运行Mutant 4,那么Test Case 5大概会失败--程序将崩溃。此处表明,通过创建一个同行变体,实际上是增强了测试方案的检测力度,由此得出的结论是,有以下两种方法,可提高测试方案的精确性:
main() { int i = 2; printf("Got %d \n", doublew(i++)+ triple(i++)); } 例3:自动生成变体
Test Case 1: input none output 12 有意思的是,这个程序因编译器的差异,而分别给出答案13或12(注:译者在Visual C++ 2005中,得出的结果是10)。假设你要编写一个这样的程序,还要能在两个不同的平台上运行,如果不同平台上的编译器有所差异,此时你会察觉到这个程序的不同,疑问由此而生:"是哪错了?"这有可能就是导致问题产生的原因。