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();
}
- 我创建了一个
build
文件夹并将 cd
放入其中,然后使用 g++ --coverage -O0 ../src/QuickMaths.cpp ../test/*.cpp -I../src/ -pthread -lgtest -lgtest_main -lgcov
进行编译
- I 运行
./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
目录中的代码在执行时没有被拾取。
出现此错误是因为您正在链接多个同名文件。
问题的线索有两条:
当运行测试时,你会看到如下警告:
libgcov profiling error:REDACTED/a-QuickMaths.gcda:overwriting an existing profile data with a different timestamp
覆盖率报告列出了三个文件:
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.cpp
、test/QuickMaths.cpp
、test/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
。
在未能获得报道后 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
进行编译
- I 运行
./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
目录中的代码在执行时没有被拾取。
出现此错误是因为您正在链接多个同名文件。
问题的线索有两条:
当运行测试时,你会看到如下警告:
libgcov profiling error:REDACTED/a-QuickMaths.gcda:overwriting an existing profile data with a different timestamp
覆盖率报告列出了三个文件:
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.cpp
、test/QuickMaths.cpp
、test/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
。