C++单元测试之二--代码覆盖率阈值检查

简介: 在上一篇我们讲到单元测试时,可用gcov来做代码覆盖率检查,但有时候我们不仅需要知道代码覆盖率,而且还要判断它是否达到我们实现设定的阈值,比如90%,如果没有达到,就打印警告信息。我们可以自己写一个脚本来实现此功能,并集成到make文件中运行。
在上一篇我们讲到单元测试时,可用gcov来做代码覆盖率检查,但有时候我们不仅需要知道代码覆盖率,而且还要判断它是否达到我们实现设定的阈值,比如90%,如果没有达到,就打印警告信息。
我们可以自己写一个脚本来实现此功能,并集成到make文件中运行。这里是作者用python编写的处理脚本:

点击(此处)折叠或打开

  1. #!/usr/bin/env python
  2. #
  3. #gcov_checker
  4. #Usage: gcov_checker threshold --objects A.o B.o ...

  5. import sys
  6. import os
  7. import subprocess


  8. def parse_command_line():
  9.     if len(sys.argv) 3:
  10.         sys.exit(1)

  11.     threshold = float(sys.argv[1])

  12.     if '--objects' not in sys.argv[2:]:
  13.         usage()
  14.         sys.exit(1)

  15.     gcov_options = sys.argv[2:sys.argv.index('--objects')]
  16.     gcov_objects = sys.argv[sys.argv.index('--objects') + 1:]

  17.     if len(gcov_objects) == 0:
  18.         usage()
  19.         sys.exit(1)

  20.     return threshold, gcov_options, gcov_objects


  21. def usage():
  22.     print 'gcov_checker threshold [gcov options] --objects object_file ... '


  23. def main():
  24.     threshold, gcov_options, gcov_objects = parse_command_line()

  25.     print "Code coverage:"

  26.     for i in gcov_objects:
  27.         command = 'gcov %s' % ' '.join(gcov_options)
  28.         command += (' -o %s' % i.replace('_stubbed', ''))
  29.         command += ' %s' % \
  30.             os.path.basename(i).replace('_stubbed', '').replace('.o', '.cpp')

  31.         gcov_process = subprocess.Popen(command,
  32.                                         stdout=subprocess.PIPE,
  33.                                         shell=True)
  34.         gcov_stdout_data = gcov_process.communicate()[0]

  35.         if gcov_process.returncode != 0:
  36.             print 'Coverage check for %s failed' % i
  37.             sys.exit(gcov_process.returncode)

  38.         coverage_info_per_file = [t for t in gcov_stdout_data.split('\n\n')
  39.                                   if t != '']

  40.         for file_info in coverage_info_per_file:
  41.             lines = file_info.split('\n')

  42.             if len(lines) not in [2, 3]:
  43.                 raise SyntaxError('Unable to parse gcov output')
  44.             name_line = lines[0]
  45.             coverage_line = lines[1]
  46. # print '============0=============%s' %(name_line)
  47. # name = name_line.split('\'')[0];
  48.             name = name_line.split('\'')[1];
  49. #.replace( \
  50. # os.environ['C_COMPONENT_OUTPUT_PATH'], '')
  51.             coverage = float(coverage_line.split(':')[1].split('% ')[0])

  52.             coverage_msg = '%s:%s%%' % (name, coverage)
  53.             warning_msg = 'WARNING: code coverage % \
  54.                 threshold
  55. # print '============1=============%s' %(name)
  56.             if name.endswith('.cpp'):
  57.                 if coverage >= threshold:
  58.                     print coverage_msg
  59.                 else:
  60.                     print '%s - %s' %(coverage_msg, warning_msg)

  61.     print "See *.gcov files for details."

  62. main()

同时我们需要把make文件中的目标UT改成:

点击(此处)折叠或打开

  1. UT:UTest.out
  2. ./UTest.out
  3. ./gcov_checker 90 --objects $(OBJS)

运行"make UT"后的结果为:

点击(此处)折叠或打开

  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_checker 90 --objects Main.o A.o
  8. Code coverage:
  9. Main.cpp:71.43% - WARNING: code coverage
  10. A.cpp:50.0% - WARNING: code coverage
  11. See *.gcov files for details.
可以看到,由于A.cpp的代码覆盖率不满90%,所以gcov_checker报出了warning。而Main.cpp也同时被报warning,因为它被包含在$(OBJS)中。

如果我们修改Main.cpp,增加代码测试A::Multiply如下:


点击(此处)折叠或打开

  1.         result = a.Multiply(5,6);
  2.         if(result != 30)
  3.         {
  4.                 printf("Multiply test failed!\n");
  5.                 exit(-1);
  6.         }
  7.         printf("Multiply test passed!\n");
那么编译链接后的结果是:

点击(此处)折叠或打开

  1. [root@tivu25 utcov]# make clean;make UT
  2. rm -f *.o *.gcno *.gcda *.gcov UTest.out
  3. g++ -I/home/haoqf/src/UTest/utcov -c -g -fprofile-arcs -ftest-coverage Main.cpp -o Main.o
  4. g++ -I/home/haoqf/src/UTest/utcov -c -g -fprofile-arcs -ftest-coverage A.cpp -o A.o
  5. g++ -o UTest.out Main.o A.o -lgcov
  6. ./UTest.out
  7. Sum test passed!
  8. Multiply test passed!
  9. ./gcov_checker 90 --objects Main.o A.o
  10. Code coverage:
  11. Main.cpp:66.67% - WARNING: code coverage
  12. A.cpp:100.0%
  13. See *.gcov files for details.
这时A.cpp代码覆盖率达到100%,所以gcov_checker没有报警(warning)。


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





目录
相关文章
|
4月前
|
测试技术 程序员 C++
C++单元测试GoogleTest和GoogleMock十分钟快速上手(gtest&gmock)
gtest是Google开源的一个跨平台的(Liunx、Mac OS X、Windows等)的 C++ 单元测试框架,可以帮助程序员测试 C++ 程序的结果预期。它提供了丰富的断言、致命和非致命判断、参数化、”死亡测试”等等。另一方面,gmock并不是一个独立的测试框架,而是gtest的辅助框架,主要用于模拟没有实现的类的操作,以便在没有完整类的情况下进行测试。通过配合使用gtest和gmock,开发者可以编写出更为复杂且健壮的C++单元测试。
371 0
|
4月前
|
算法 安全 编译器
【C++ 关键字 override】C++ 重写关键字override(强制编译器检查该函数是否覆盖已存在的虚函数)
【C++ 关键字 override】C++ 重写关键字override(强制编译器检查该函数是否覆盖已存在的虚函数)
71 0
|
1月前
|
IDE 开发工具 Android开发
Android c++ core guideline checker 应用问题之clang-tidy 检查后发现的问题如何解决
Android c++ core guideline checker 应用问题之clang-tidy 检查后发现的问题如何解决
|
3月前
|
jenkins 测试技术 持续交付
利用C++增强框架的可测试性(Testability)
**C++框架可测试性提升策略**:通过模块化设计、依赖注入、使用Mock对象和Stub、编写清晰接口及文档、断言与异常处理、分离测试代码与生产代码、自动化测试,可以有效增强C++框架的可测试性。这些方法有助于确保代码正确性、健壮性,提高可维护性和可扩展性。示例包括使用类和接口实现模块化,通过构造函数进行依赖注入,以及利用Google Test和Google Mock进行断言和模拟测试。
53 1
|
4月前
|
算法 TensorFlow 算法框架/工具
基于直方图的图像阈值计算和分割算法FPGA实现,包含tb测试文件和MATLAB辅助验证
这是一个关于图像处理的算法实现摘要,主要包括四部分:展示了四张算法运行的效果图;提到了使用的软件版本为VIVADO 2019.2和matlab 2022a;介绍了算法理论,即基于直方图的图像阈值分割,通过灰度直方图分布选取阈值来区分图像区域;并提供了部分Verilog代码,该代码读取图像数据,进行处理,并输出结果到"result.txt"以供MATLAB显示图像分割效果。
|
4月前
|
C++
【C++医学影像PACS】CT检查中的三维重建是什么检查?
【C++医学影像PACS】CT检查中的三维重建是什么检查?
132 0
|
4月前
|
安全 算法 编译器
【C++ 静态断言的技巧】掌握C++中static_assert的力量:深入探讨编译时检查
【C++ 静态断言的技巧】掌握C++中static_assert的力量:深入探讨编译时检查
84 1
|
4月前
|
存储 缓存 安全
【C/C++ 关键字 存储类说明符】C/C++ 的mutable 关键字 忽略对该数据成员的常量性检查在const函数中修改变量值
【C/C++ 关键字 存储类说明符】C/C++ 的mutable 关键字 忽略对该数据成员的常量性检查在const函数中修改变量值
49 0
|
4月前
|
安全 编译器 程序员
【C++ 泛型编程 高级篇】C++ 编程深掘:静态成员函数检查的艺术与实践
【C++ 泛型编程 高级篇】C++ 编程深掘:静态成员函数检查的艺术与实践
107 0
|
4月前
|
XML 算法 C语言
【C/C++ 静态代码检查工具 Cppcheck 】Cppcheck 检测器列表和检查规则大全一览
【C/C++ 静态代码检查工具 Cppcheck 】Cppcheck 检测器列表和检查规则大全一览
344 0