Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1950078
  • 博文数量: 77
  • 博客积分: 2175
  • 博客等级: 大尉
  • 技术积分: 2491
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-20 20:49
个人简介

欢迎光临我的博客

文章分类

全部博文(77)

文章存档

2023年(1)

2018年(4)

2017年(1)

2016年(2)

2015年(2)

2013年(5)

2012年(29)

2010年(33)

分类: C/C++

2012-08-22 15:51:47

在上一篇我们讲到单元测试时,可用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 < %.2f%%' % \
  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 < 90.00%
  10. A.cpp:50.0% - WARNING: code coverage < 90.00%
  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 < 90.00%
  12. A.cpp:100.0%
  13. See *.gcov files for details.
这时A.cpp代码覆盖率达到100%,所以gcov_checker没有报警(warning)。


《返璞归真--UNIX技术内幕》在全国各大书店及网城均有销售:

                         
                       





阅读(9888) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~