C++单元测试之一--利用gcov做代码覆盖率检查

简介:     单元测试(unit test)是一种白盒测试,它是开发人员对自己编写的代码所做的测试。所谓白盒测试,就是浏览并测试代码的各个部分和分支。一般它需要开发人员自己写一些测试代码,来调用被测代码的接口,并通过测试结果来判断被测代码是否正确工作。
    单元测试(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号店




目录
相关文章
|
6月前
|
测试技术 程序员 C++
C++单元测试GoogleTest和GoogleMock十分钟快速上手(gtest&gmock)
gtest是Google开源的一个跨平台的(Liunx、Mac OS X、Windows等)的 C++ 单元测试框架,可以帮助程序员测试 C++ 程序的结果预期。它提供了丰富的断言、致命和非致命判断、参数化、”死亡测试”等等。另一方面,gmock并不是一个独立的测试框架,而是gtest的辅助框架,主要用于模拟没有实现的类的操作,以便在没有完整类的情况下进行测试。通过配合使用gtest和gmock,开发者可以编写出更为复杂且健壮的C++单元测试。
487 0
|
6月前
|
算法 安全 编译器
【C++ 关键字 override】C++ 重写关键字override(强制编译器检查该函数是否覆盖已存在的虚函数)
【C++ 关键字 override】C++ 重写关键字override(强制编译器检查该函数是否覆盖已存在的虚函数)
95 0
|
3月前
|
IDE 开发工具 Android开发
Android c++ core guideline checker 应用问题之clang-tidy 检查后发现的问题如何解决
Android c++ core guideline checker 应用问题之clang-tidy 检查后发现的问题如何解决
|
5月前
|
jenkins 测试技术 持续交付
利用C++增强框架的可测试性(Testability)
**C++框架可测试性提升策略**:通过模块化设计、依赖注入、使用Mock对象和Stub、编写清晰接口及文档、断言与异常处理、分离测试代码与生产代码、自动化测试,可以有效增强C++框架的可测试性。这些方法有助于确保代码正确性、健壮性,提高可维护性和可扩展性。示例包括使用类和接口实现模块化,通过构造函数进行依赖注入,以及利用Google Test和Google Mock进行断言和模拟测试。
79 1
|
6月前
|
C++
【C++医学影像PACS】CT检查中的三维重建是什么检查?
【C++医学影像PACS】CT检查中的三维重建是什么检查?
165 0
|
6月前
|
安全 算法 编译器
【C++ 静态断言的技巧】掌握C++中static_assert的力量:深入探讨编译时检查
【C++ 静态断言的技巧】掌握C++中static_assert的力量:深入探讨编译时检查
131 1
|
6月前
|
存储 缓存 安全
【C/C++ 关键字 存储类说明符】C/C++ 的mutable 关键字 忽略对该数据成员的常量性检查在const函数中修改变量值
【C/C++ 关键字 存储类说明符】C/C++ 的mutable 关键字 忽略对该数据成员的常量性检查在const函数中修改变量值
66 0
|
6月前
|
安全 编译器 程序员
【C++ 泛型编程 高级篇】C++ 编程深掘:静态成员函数检查的艺术与实践
【C++ 泛型编程 高级篇】C++ 编程深掘:静态成员函数检查的艺术与实践
145 0
|
6月前
|
XML 算法 C语言
【C/C++ 静态代码检查工具 Cppcheck 】Cppcheck 检测器列表和检查规则大全一览
【C/C++ 静态代码检查工具 Cppcheck 】Cppcheck 检测器列表和检查规则大全一览
518 0
|
6月前
|
缓存 运维 Serverless
应用研发平台EMAS产品常见问题之测试检查更新没有反应如何解决
应用研发平台EMAS(Enterprise Mobile Application Service)是阿里云提供的一个全栈移动应用开发平台,集成了应用开发、测试、部署、监控和运营服务;本合集旨在总结EMAS产品在应用开发和运维过程中的常见问题及解决方案,助力开发者和企业高效解决技术难题,加速移动应用的上线和稳定运行。