在上一篇我们讲到单元测试时,可用gcov来做代码覆盖率检查,但有时候我们不仅需要知道代码覆盖率,而且还要判断它是否达到我们实现设定的阈值,比如90%,如果没有达到,就打印警告信息。
我们可以自己写一个脚本来实现此功能,并集成到make文件中运行。这里是作者用python编写的处理脚本:
同时我们需要把make文件中的目标UT改成:
运行"make UT"后的结果为:
可以看到,由于A.cpp的代码覆盖率不满90%,所以gcov_checker报出了warning。而Main.cpp也同时被报warning,因为它被包含在$(OBJS)中。
如果我们修改Main.cpp,增加代码测试A::Multiply如下:
那么编译链接后的结果是:
这时A.cpp代码覆盖率达到100%,所以gcov_checker没有报警(warning)。
《返璞归真--UNIX技术内幕》在全国各大书店及网城均有销售:
京东
亚马逊 China pub
上学吧 1号店
我们可以自己写一个脚本来实现此功能,并集成到make文件中运行。这里是作者用python编写的处理脚本:
点击(此处)折叠或打开
- #!/usr/bin/env python
- #
- #gcov_checker
- #Usage: gcov_checker threshold --objects A.o B.o ...
- import sys
- import os
- import subprocess
- def parse_command_line():
- if len(sys.argv) 3:
- sys.exit(1)
- threshold = float(sys.argv[1])
- if '--objects' not in sys.argv[2:]:
- usage()
- sys.exit(1)
- gcov_options = sys.argv[2:sys.argv.index('--objects')]
- gcov_objects = sys.argv[sys.argv.index('--objects') + 1:]
- if len(gcov_objects) == 0:
- usage()
- sys.exit(1)
- return threshold, gcov_options, gcov_objects
- def usage():
- print 'gcov_checker threshold [gcov options] --objects object_file ... '
- def main():
- threshold, gcov_options, gcov_objects = parse_command_line()
- print "Code coverage:"
- for i in gcov_objects:
- command = 'gcov %s' % ' '.join(gcov_options)
- command += (' -o %s' % i.replace('_stubbed', ''))
- command += ' %s' % \
- os.path.basename(i).replace('_stubbed', '').replace('.o', '.cpp')
- gcov_process = subprocess.Popen(command,
- stdout=subprocess.PIPE,
- shell=True)
- gcov_stdout_data = gcov_process.communicate()[0]
- if gcov_process.returncode != 0:
- print 'Coverage check for %s failed' % i
- sys.exit(gcov_process.returncode)
- coverage_info_per_file = [t for t in gcov_stdout_data.split('\n\n')
- if t != '']
- for file_info in coverage_info_per_file:
- lines = file_info.split('\n')
- if len(lines) not in [2, 3]:
- raise SyntaxError('Unable to parse gcov output')
- name_line = lines[0]
- coverage_line = lines[1]
- # print '============0=============%s' %(name_line)
- # name = name_line.split('\'')[0];
- name = name_line.split('\'')[1];
- #.replace( \
- # os.environ['C_COMPONENT_OUTPUT_PATH'], '')
- coverage = float(coverage_line.split(':')[1].split('% ')[0])
- coverage_msg = '%s:%s%%' % (name, coverage)
- warning_msg = 'WARNING: code coverage % \
- threshold
- # print '============1=============%s' %(name)
- if name.endswith('.cpp'):
- if coverage >= threshold:
- print coverage_msg
- else:
- print '%s - %s' %(coverage_msg, warning_msg)
- print "See *.gcov files for details."
- main()
同时我们需要把make文件中的目标UT改成:
点击(此处)折叠或打开
- UT:UTest.out
- ./UTest.out
- ./gcov_checker 90 --objects $(OBJS)
运行"make UT"后的结果为:
点击(此处)折叠或打开
- [root@tivu25 utcov]# make UT
- g++ -I/home/haoqf/src/UTest/utcov -c -g -fprofile-arcs -ftest-coverage Main.cpp -o Main.o
- g++ -I/home/haoqf/src/UTest/utcov -c -g -fprofile-arcs -ftest-coverage A.cpp -o A.o
- g++ -o UTest.out Main.o A.o -lgcov
- ./UTest.out
- Sum test passed!
- ./gcov_checker 90 --objects Main.o A.o
- Code coverage:
- Main.cpp:71.43% - WARNING: code coverage
- A.cpp:50.0% - WARNING: code coverage
- See *.gcov files for details.
如果我们修改Main.cpp,增加代码测试A::Multiply如下:
点击(此处)折叠或打开
- result = a.Multiply(5,6);
- if(result != 30)
- {
- printf("Multiply test failed!\n");
- exit(-1);
- }
- printf("Multiply test passed!\n");
点击(此处)折叠或打开
- [root@tivu25 utcov]# make clean;make UT
- rm -f *.o *.gcno *.gcda *.gcov UTest.out
- g++ -I/home/haoqf/src/UTest/utcov -c -g -fprofile-arcs -ftest-coverage Main.cpp -o Main.o
- g++ -I/home/haoqf/src/UTest/utcov -c -g -fprofile-arcs -ftest-coverage A.cpp -o A.o
- g++ -o UTest.out Main.o A.o -lgcov
- ./UTest.out
- Sum test passed!
- Multiply test passed!
- ./gcov_checker 90 --objects Main.o A.o
- Code coverage:
- Main.cpp:66.67% - WARNING: code coverage
- A.cpp:100.0%
- See *.gcov files for details.
《返璞归真--UNIX技术内幕》在全国各大书店及网城均有销售:
京东
亚马逊 China pub
上学吧 1号店