gcov 覆盖范围仅限于最小 g++ 项目中的测试文件

gcov coverage limited to test files in minimal g++ project

在未能获得报道后 with-cmake 我设置了一个简约项目,看看我是否可以通过这种方式获得报道。 它源自 using-gtest-without-cmake

它有一个 src 文件夹,里面有头文件和源文件。 QuickMaths.hpp :

#include <cstdint>

using size_t = std::size_t;

size_t
multiply(size_t a, size_t b);

inline size_t
add(size_t a, size_t b)
{
  return a + b;
}

class QuickMaths
{
public:
  size_t operator*() const;
  friend QuickMaths operator+(QuickMaths const&, QuickMaths const&);

  QuickMaths(size_t x);

private:
  size_t x;
};

QuickMaths.cpp:

#include "QuickMaths.hpp"

size_t
multiply(size_t a, size_t b)
{
  return a * b;
}

size_t
QuickMaths::operator*() const
{
  return x;
}

QuickMaths::QuickMaths(size_t x)
  : x(x)
{}

QuickMaths
operator+(QuickMaths const& a, QuickMaths const& b)
{
  return a.x + b.x;
}

还有一个测试文件夹 QuickMaths.cpp :

#include <gtest/gtest.h>

#include <QuickMaths.hpp>

TEST(AddTest, shouldAdd)
{
  EXPECT_EQ(add(1UL, 1UL), 2UL);
}

TEST(MultiplyTest, shouldMultiply)
{
  EXPECT_EQ(multiply(2UL, 4UL), 8UL);
}

TEST(QuickMathTest, haveValue)
{
  auto v = QuickMaths{ 4UL };
  EXPECT_EQ(*v, 4UL);
}

和main.cpp:

#include <gtest/gtest.h>

int
main(int argc, char** argv)
{
  testing::InitGoogleTest(&argc, argv);

  return RUN_ALL_TESTS();
}

最后我 运行 gcovr -r ../ . 得到以下输出:

------------------------------------------------------------------------------
                           GCC Code Coverage Report
Directory: ../
------------------------------------------------------------------------------
File                                       Lines    Exec  Cover   Missing
------------------------------------------------------------------------------
src/QuickMaths.hpp                             2       0     0%   9,11
test/QuickMaths.cpp                            7       0     0%   5,7,10,12,15,17-18
test/main.cpp                                  3       3   100%   
------------------------------------------------------------------------------
TOTAL                                         12       3    25%
------------------------------------------------------------------------------

所以可以看到位于 main 中的 gtest 设置正在被拾取,但是测试用例本身以及 src 目录中的代码在执行时没有被拾取。

出现此错误是因为您正在链接多个同名文件。

问题的线索有两条:

  1. 当运行测试时,你会看到如下警告:

    libgcov profiling error:REDACTED/a-QuickMaths.gcda:overwriting an existing profile data with a different timestamp
    
  2. 覆盖率报告列出了三个文件:

    • src/QuickMaths.hpp
    • test/QuickMaths.cpp
    • test/main.cpp

    但是有一个文件完全丢失了:

    • src/QuickMaths.cpp

发生了什么事?

  • 当您的测试关闭时,原始覆盖率数据由测试进程写入 .gcda 文件。这些文件的名称取决于编译单元。

  • 查看您的构建目录,我们看到以下数据 (.gcda) 和注释 (.gcno) 文件:

    build
    |-- a-QuickMaths.gcda
    |-- a-QuickMaths.gcno
    |-- a-main.gcda
    |-- a-main.gcno
    `-- a.out
    
  • 您总共向编译命令提供了三个文件

    • 你的命令是g++ ... ../src/QuickMaths.cpp ../test/*.cpp ....
    • 三个文件分别是src/QuickMaths.cpptest/QuickMaths.cpptest/main.cpp
  • 编译单元的自动生成名称似乎只考虑了输入文件的基本名称,忽略了目录。由于两个文件具有相同的基本名称,因此使用相同的编译单元名称 a-QuickMaths

  • 由于编译单元存在名称冲突,因此覆盖率数据文件名称也存在冲突。

  • 结果是损坏的覆盖率数据。

解决方法是分别编译每个编译单元,然后再链接。您必须为每个编译单元指定一个不同的名称,可能使用多个子目录。例如:

set -euo pipefail

# compile foo/bar.cpp -> build/foo/bar.o
for source in src/*.cpp test/*.cpp; do
  mkdir -p build/"$(dirname "$source")"
  cd build
  g++ --coverage -O0 -pthread -I../src -c -o "${source%.cpp}".o ../"${source}"
  cd -
done

# link the tests
cd build;
g++ --coverage -pthread -o testcase src/*.o test/*.o -lgtest
cd -

# run the test
cd build
./testcase
cd -

tree build  # show directory structure

# run gcovr
cd build
gcovr -r ..
cd -

在此示例中,构建目录如下所示:

build
|-- src
|   |-- QuickMaths.gcda
|   |-- QuickMaths.gcno
|   `-- QuickMaths.o
|-- test
|   |-- QuickMaths.gcda
|   |-- QuickMaths.gcno
|   |-- QuickMaths.o
|   |-- main.gcda
|   |-- main.gcno
|   `-- main.o
`-- testcase

覆盖率报告符合预期:

------------------------------------------------------------------------------
                           GCC Code Coverage Report
Directory: ..
------------------------------------------------------------------------------
File                                       Lines    Exec  Cover   Missing
------------------------------------------------------------------------------
src/QuickMaths.cpp                             9       7    77%   20,22
src/QuickMaths.hpp                             2       2   100%   
test/QuickMaths.cpp                           10      10   100%   
test/main.cpp                                  3       3   100%   
------------------------------------------------------------------------------
TOTAL                                         24      22    91%
------------------------------------------------------------------------------

补充说明:

  • 您提供了 main(),但也链接了 -lgtest_main。这是不必要的。
  • --coverage 标志已经包含 -lgcov