作为我单元测试的一部分,我希望确保代码覆盖测试。目的是在代码的某处放置类似REQUIRE_TEST
的宏,并检查是否调用了所有这些宏。查找未执行的C++代码行
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)使用宏来计算宏 - 但之后我不知道哪些特定的REQUIRE_TEST宏是不是calle d ...(如果别人决定使用__COUNTER__
宏以及一切休息...)
是否有解决这个问题的任何解决方案,得体?我错过了什么?它 会很高兴有一个宏附加当前行和文件 所以一些预处理器变量,只要它被调用 - 但这不是 可能,对吧?有没有其他的方法可以在
main()
之前执行的 之类的东西可以在函数体内完成?
研究编译器的警告和命令行选项。许多编译器都有能力识别“死代码”。 –
TL; DR;为什么不使用像''gcov'](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html)这样的覆盖率分析代码注入并分析结果,例如使用['lcov'](http://ltp.sourceforge.net/coverage/lcov.php)?如果_dead code_没有从您的测试场景中执行,那么这可能不一定真正批准。一个静态代码分析工具可能会更好地找到这种死的东西。 –
@πάνταῥεῖ'gcov'非常详细 - 但也代码部分我不太在意。像“REQUIRE_TEST”这样的标记可以让我指定我关心的部分。它也将成为我的图书馆所有人的另一个依赖 - 并且它感觉像C++几乎可以做我想做的事情......如果我的任何尝试工作,我会拥有我想要的一切。也许像'gcov'这样的结果将是唯一的解决方案 - 但我想知道,我所尝试的是不可能的,然后再“放弃”并添加另一个依赖项... – example