【发布时间】:2015-07-06 08:35:02
【问题描述】:
作为单元测试的一部分,我想确保测试的代码覆盖率。目的是在代码中的某处放置类似 REQUIRE_TEST 的宏,并检查是否所有这些都被调用了。
void foo(bool b) {
if (b) {
REQUIRE_TEST
...
} else {
REQUIRE_TEST
...
}
}
void main() {
foo(true);
output_all_missed_REQUIRE_macros();
}
理想情况下,输出应包括源文件和宏行。
我最初的想法是让宏创建静态对象,这些对象会在某个地图中注册自己,然后检查是否所有这些都被调用
#define REQUIRE_TEST \
do { \
static ___RequiredTest requiredTest(__func__, __FILE__, __LINE__);\
(void)requiredTest;\
___RequiredTest::increaseCounter(__func__, __FILE__, __LINE__);\
} while(false)
但静态对象仅在第一次调用代码时创建。所以地图只包含下一行也计算在内的函数 - 找不到缺少的 REQUIRE_TEST 宏。在这种情况下,__attribute__((used)) 将被忽略。
gcc 有一个不错的属性__attribute__((constructor)),但是放在这里时显然选择忽略它(跟随代码而不是静态对象)
struct teststruct { \
__attribute__((constructor)) static void bla() {\
___RequiredTest::register(__func__, __FILE__, __LINE__); \
} \
};\
也为
[]() __attribute__((constructor)) { \
___RequiredTest::register(__func__, __FILE__, __LINE__); \
};\
我现在能想到的唯一方法是 a) 手动(或通过脚本)分析常规编译之外的代码 (uargh) 或 b) 使用 __COUNTER__ 宏来计算宏 - 但我会不知道哪些特定的 REQUIRE_TEST 宏没有被调用...(如果其他人也决定使用 __COUNTER__ 宏,一切都会中断...)
这个问题有什么好的解决办法吗?我错过了什么?它 有一个附加当前行和文件的宏会很好 所以无论何时调用一些预处理器变量 - 但那不是 可能,对吧?有没有其他方法可以注册某些东西 在
main()之前执行,可以在函数体内完成吗?
【问题讨论】:
-
研究编译器的警告和命令行选项。许多编译器具有识别“死代码”的能力。
-
@πάνταῥεῖ
gcov非常详细 - 但在我并不关心的代码部分也是如此。放置像REQUIRE_TEST这样的标记可以让我指定我关心的部分。对于我将库交付给的每个人来说,这也是另一个依赖项 - 感觉 C++几乎 能够做我想做的事......如果我的任何尝试成功,我将拥有我想要的一切.也许像gcov这样的东西最终将是唯一的解决方案 - 但我想知道在“放弃”并添加另一个依赖项之前我正在尝试的事情是不可能的......
标签: c++ c++11 macros g++ code-coverage