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

发布于 2025-01-16 10:04:21 字数 2820 浏览 1 评论 0原文

未能获得覆盖范围 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();
}
  • 我创建一个 build 文件夹并 cd 进入其中,然后使用 g++ --coverage -O0 ../src/ 进行编译QuickMaths.cpp ../test/*.cpp -I../src/ -pthread -lgtest -lgtest_main -lgcov
  • 我运行 ./a.out =>输出显示测试正在运行并通过

最后我运行 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 目录中的代码在执行时不会被拾取。

After failing to get coverage with-cmake I set up a minimalistic project to see if I can get coverage working that way.
It's derived from using-gtest-without-cmake

It has a src folder with a header and source file in it.
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;
}

And a test folder with
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);
}

and main.cpp :

#include <gtest/gtest.h>

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

  return RUN_ALL_TESTS();
}
  • I create a build folder and cd into it, then compile using g++ --coverage -O0 ../src/QuickMaths.cpp ../test/*.cpp -I../src/ -pthread -lgtest -lgtest_main -lgcov
  • I run ./a.out => output shows tests being run and passing

Lastly I run gcovr -r ../ . and get the following output:

------------------------------------------------------------------------------
                           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%
------------------------------------------------------------------------------

So it's visible that the gtest setup situated in main is being picked up, but the test cases themselves as well as the code from the src directory is not picked up as executed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

悲欢浪云 2025-01-23 10:04:21

发生此错误的原因是您链接多个同名文件。

该问题有两个线索:

  1. 运行测试时,您将看到如下警告:

    libgcov 分析错误:已编辑/a-QuickMaths.gcda:使用不同的时间戳覆盖现有的配置文件数据
    
  2. 覆盖率报告列出了三个文件:

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

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

    • src/QuickMaths.cpp

发生了什么?

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

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

    构建
    |-- 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

This error occurs because you are linking multiple files with the same name.

There are two clues to the problem:

  1. When running the test, you will see a warning such as the following:

    libgcov profiling error:REDACTED/a-QuickMaths.gcda:overwriting an existing profile data with a different timestamp
    
  2. The coverage report lists three files:

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

    But one file is missing entirely:

    • src/QuickMaths.cpp

What has happened?

  • When your tests shut down, raw coverage data is written by the test process into .gcda files. The name of these files depends on the compilation unit.

  • Looking into your build dir, we see the following data (.gcda) and notes (.gcno) files:

    build
    |-- a-QuickMaths.gcda
    |-- a-QuickMaths.gcno
    |-- a-main.gcda
    |-- a-main.gcno
    `-- a.out
    
  • You have provided a total of three files to your compilation command

    • Your command is g++ ... ../src/QuickMaths.cpp ../test/*.cpp ....
    • The three files are src/QuickMaths.cpp, test/QuickMaths.cpp, test/main.cpp
  • The autogenerated names for the compilation units seems to only consider the input file's basename, ignoring the directory. Since two files have the same basename, the same name for the compilation unit a-QuickMaths is used.

  • Since there's a name clash for the compilation unit, there is also a conflict for the coverage data file names.

  • The result is corrupted coverage data.

The solution is to compile each compilation unit separately and linking them afterwards. You must give each compilation unit a distinct name, possibly using multiple subdirectories. For example:

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 -

In this example, the build directory would look like:

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

And the coverage report is as expected:

------------------------------------------------------------------------------
                           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%
------------------------------------------------------------------------------

Additional notes:

  • You're providing a main() but are also linking -lgtest_main. This is unnecessary.
  • The --coverage flag already includes -lgcov.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文