单元测试(unit test)是一种白盒测试,它是开发人员对自己编写的代码所做的测试。所谓白盒测试,就是浏览并测试代码的各个部分和分支。一般它需要开发人员自己写一些测试代码,来调用被测代码的接口,并通过测试结果来判断被测代码是否正确工作。下面是一个简单的例子。
被测类A的声明

点击(此处)折叠或打开

  1. //A.h
  2. #ifndef _A_H_
  3. #define _A_H_
  4. class A
  5. {
  6. public:
  7.     int Sum(int a, int b);
  8.     int Multiply(int a, int b);
  9. };

  10. #endif


被测类A的定义:

点击(此处)折叠或打开

  1. //A.cpp
  2. #include "A.h"
  3. #include <stdio.h>


  4. int A::Sum(int a, int b)
  5. {
  6.     return a+b;
  7. }

  8. int A::Multiply(int a, int b)
  9. {
  10.     return a*b;
  11. }




测试代码:

点击(此处)折叠或打开

  1. //Main.cpp
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. int main(int argc, char *argv[])
  5. {
  6.         A a;
  7.         int result=a.Sum(5, 6);
  8.         if(result != 11)
  9.         {
  10.                 printf("Sum test failed!\n");
  11.                 exit(-1);
  12.         }
  13.         printf("Sum test passed!\n");
  14.     

  15.     return 0;
  16. }
linux下的make文件是:

点击(此处)折叠或打开

  1. OBJS= Main.o A.o

  2. UTest.out: $(OBJS)
  3.         g++ -o UTest.out $(OBJS)

  4. CURDIR=$(shell pwd)

  5. $(OBJS): %.o: %.cpp
  6.         g++ -I$(CURDIR) -c -g $< -o $@

  7. #unit test
  8. UT:UTest.out
  9.         ./UTest.out

  10. .PHONY: clean
  11. clean:
  12.         rm -f *.o UTest.out


编译运行后的结果是:

点击(此处)折叠或打开

  1. [root@tivu25 utcov]# make UT
  2. g++ -I/home/haoqf/src/UTest/utcov -c -g Main.cpp -o Main.o
  3. g++ -I/home/haoqf/src/UTest/utcov -c -g A.cpp -o A.o
  4. g++ -o UTest.out Main.o A.o
  5. ./UTest.out
  6. Sum test



我们知道A::Sum函数的第一个用例测试通过了,但这时我们并不知道A.cpp当中哪些代码被测过,哪些代码没有被测过,也不知道代码覆盖率(虽然对于目前这个简单的程序肉眼是可以看出来,A::Sum函数被测,A::Multiply函数没被测,但如果被测代码非常复杂,函数之间的嵌套调用很多,函数的处理分支如if判断和while, for循环等也很多,那么就很难以人工判断哪些分支被测,哪些没被测。而且,测试代码是动态运行的)。
在linux平台下,我们可以利用系统工具gcov来实现这一点。这需要改写make文件如下:


点击(此处)折叠或打开

  1. OBJS= Main.o A.o

  2. UTest.out: $(OBJS)
  3.         g++ -o UTest.out $(OBJS) -lgcov

  4. CURDIR=$(shell pwd)

  5. $(OBJS): %.o: %.cpp
  6.         g++ -I$(CURDIR) -c -g -fprofile-arcs -ftest-coverage $< -o $@

  7. #unit test and code coverage check
  8. UT:UTest.out
  9.         ./UTest.out
  10.         gcov -o A.o A.cpp

  11. .PHONY: clean
  12. clean:
  13.         rm -f *.o *.gcno *.gcda *.gcov UTest.out
注意到不同了吗?编译时增加了选项"-ftest-coverage",链接时增加了" -lgcov",运行时增加了命令:
gcov -o A.o A.cpp。
运行结果是:

点击(此处)折叠或打开

  1. [root@tivu25 utcov]# make UT
  2. g++ -I/home/haoqf/src/UTest/utcov -c -g -fprofile-arcs -ftest-coverage Main.cpp -o Main.o
  3. g++ -I/home/haoqf/src/UTest/utcov -c -g -fprofile-arcs -ftest-coverage A.cpp -o A.o
  4. g++ -o UTest.out Main.o A.o -lgcov
  5. ./UTest.out
  6. Sum test passed!
  7. gcov -o A.o A.cpp
  8. File 'A.cpp'
  9. Lines executed:50.00% of 4
  10. A.cpp:creating 'A.cpp.gcov'
gcov给我们报出来代码覆盖率:
Lines executed:50.00% of 4
其意思是:A.cpp一共有4行(可执行代码),被测了50%。
具体哪些代码被测还可以看A.cpp.gcov文件:


点击(此处)折叠或打开

  1. -: 0:Source:A.cpp
  2.         -: 0:Graph:A.gcno
  3.         -: 0:Data:A.gcda
  4.         -: 0:Runs:1
  5.         -: 0:Programs:1
  6.         -: 1:#include "A.h"
  7.         -: 2:#include <stdio.h>
  8.         -: 3:
  9.         -: 4:
  10.         1: 5:int A::Sum(int a, int b)
  11.         -: 6:{
  12.         1: 7: return a+b;
  13.         -: 8:}
  14.         -: 9:
  15.     #####: 10:int A::Multiply(int a, int b)
  16.         -: 11:{
  17.     #####: 12: return a*b;
  18.         -: 13:}
-表示该行不可执行,数字1或其他表示该行被执行了多少次,#####表示代码没被执行。从中我们可以看出函数Multiply没被执行,这是对的,它确实没有被测试代码所执行。



《返璞归真--UNIX技术内幕》在全国各大书店及网城均有销售:
京东
亚马逊                          China pub
上学吧                          1号店




09-05 00:58