我使用lcov2.0来检测分支覆盖率,但是会遇到很多和std容器相关的分支未覆盖的问题。
- g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
- gtest 1.12.x
- lcov/genhtml: LCOV version 2.0-1
源码
// src/main.hpp
#include <cstdint>
#include <iostream>
#include <map>
#include <set>
#include <stdexcept>
using namespace std;
class mytestint
{
public:
mytestint() = default;
mytestint(uint16_t id, uint16_t pr) : _id(id), _pr(pr) {}
uint16_t get_id() const
{
return _id;
}
private:
uint16_t _id;
uint16_t _pr;
};
map<uint16_t, mytestint> _test_map;
map<uint16_t, uint16_t> _test_map_pod;
void test_emplace(uint16_t id, uint16_t pr)
{
// map with class
mytestint temp = {id, pr};
auto t = _test_map.emplace(id, temp);
auto k = _test_map.emplace(id, mytestint(id,pr));
auto s = _test_map.insert({pr, temp});
_test_map[id] = temp;
auto h = _test_map[pr];
// map with uint16_t
_test_map_pod.emplace(id,pr);
_test_map_pod.insert({pr,id});
_test_map_pod[id] = pr;
}
gtest代码
#include "src/main.hpp"
#include <gtest/gtest.h>
TEST(MapTest, TestMap) {
EXPECT_NO_THROW(test_emplace(1,1));
EXPECT_NO_THROW(test_emplace(2,2));
EXPECT_NO_THROW(test_emplace(3,3));
EXPECT_NO_THROW(test_emplace(2,4));
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
lcov最终生成的报告长这样,所有insert和emplace相关的函数都会有一个未解决的分支
92 : 4 : void test_emplace(uint16_t id, uint16_t pr)
93 : : {
94 : : // map with class
95 : 4 : mytestint temp = {id, pr};
96 [ + - ]: 4 : auto t = _test_map.emplace(id, temp);
97 [ + - ]: 4 : auto k = _test_map.emplace(id, mytestint(id,pr));
98 [ + - ]: 4 : auto s = _test_map.insert({pr, temp});
99 [ + - ]: 4 : _test_map[id] = temp;
100 [ + - ]: 4 : auto h = _test_map[pr];
101 : : // map with uint16_t
102 [ + - ]: 4 : _test_map_pod.emplace(id,pr);
103 [ + - ]: 4 : _test_map_pod.insert({pr,id});
104 [ + - ]: 4 : _test_map_pod[id] = pr;
105 : 4 : }
贴出我用的lcov命令
g++ -std=c++17 test.cpp -o test -lgtest -lgtest_main -pthread -fprofile-arcs -ftest-coverage -fprofile-update=atomic && \
./test && \
gcov -o . test.cpp && \
lcov --capture \
--rc branch_coverage=1 \
--directory . \
--output-file coverage_all.info \
--ignore-errors mismatch && \
lcov --remove coverage_all.info '*/usr/include/*' '*/usr/lib/*' '*/usr/lib64/*' \
'*/usr/local/include/*' '*/usr/local/lib/*' \
'*/usr/local/lib64/*' \
--rc branch_coverage=1 \
--output-file coverage.info \
--ignore-errors unused \
--ignore-errors mismatch && \
genhtml coverage.info \
--rc branch_coverage=1 \
--output-directory coverage_report
我想知道要怎么覆盖上这些分支?因为现在要求分支覆盖率要达到某个百分比,但是代码里面有一大堆std库函数的操作而产生的分支,这些和自己实现的代码没有联系的分支很难被完全测试出来……
就想知道这里的分支未覆盖和这几个插入函数中的异常处理有关系吗?我看so上面一个远古帖子说在g++编译的时候屏蔽这些异常能解决一些分支。但是那样就完全没有办法使用try/catch等异常处理语句了,肯定不是个解决办法。
lcov用的人似乎太少了,国内和外网都没有找到一个很细致的分支覆盖率提高的教程(也有可能是我搜索的方式不对吧……很少上外网搜东西。)
关联问题 https://segmentfault.com/q/1010000044378276
C++的lcov隐藏未覆盖分支确实让人头疼,十分感谢指出了主要原因,最后我们使用了下述方法解决:
然后在gtest的编译脚本中启用了 -fno-exceptions -DUNIT_TEST 编译选项解决了令人讨厌的未覆盖分支问题