我正在使用VS2005 VC ++来管理非托管C ++。我有VSTS,我正在尝试使用代码覆盖工具来完成关于单元测试的两件事:
设置VSTS代码覆盖率工具(请参阅link text)并完成任务#1非常简单。然而#2对我来说是一个令人惊讶的挑战。这是我的测试代码。
class CodeCoverageTarget
{
public:
std::string ThisMethodRuns() {
return "Running";
}
std::string ThisMethodDoesNotRun() {
return "Not Running";
}
};
#include <iostream>
#include "CodeCoverageTarget.h"
using namespace std;
int main()
{
CodeCoverageTarget cct;
cout<<cct.ThisMethodRuns()<<endl;
}
当如上所述在类中定义两个方法时,编译器会自动从obj文件中删除ThisMethodDoesNotRun()。如果我在类外移动它的定义,那么它将包含在obj文件中,代码覆盖工具显示它根本没有被执行。在大多数情况下,我希望编译器为我做这个消除,但对于代码覆盖率工具,它会击败该值的很大一部分(例如,找到未经测试的方法)。我已经尝试了很多东西来告诉编译器不要再聪明地编译所有内容但是我很难过。如果代码覆盖率工具对此进行补偿(我想通过扫描源并将其与链接器输出匹配)会很好,但我没有发现任何暗示它有特殊模式要打开的东西。我在这里完全遗漏了一些简单的东西,或者VC ++编译器+ VSTS代码覆盖工具是不可能的?
提前致谢, KGB
答案 0 :(得分:1)
您可以尝试添加一行代码来仅在某些条件为真时调用该函数,并保证该条件永远不会为真。只要确保编译器无法解决这个问题。例如,
int main(int argc, char **argv)
{
if(argv == NULL) // C runtime says this won't happen
someMethodWhichIsntReallyEverCalled();
}
答案 1 :(得分:1)
确保您的功能不被丢弃的一种方法是导出它们。您可以通过在函数声明中添加__declspec(dllexport)
来完成此操作。最好将它包装在C预处理器宏中,以便您可以将其关闭,因为它是特定于编译器的,您可能不希望所有构建都导出符号。导出函数的另一种方法是创建.DEF
file。
如果内联是问题所在,您可能也会使用__declspec(noinline)
取得成功。
您的代码是否在静态库中,然后编译成测试EXE / DLL?链接器将自动丢弃静态库中未引用的目标文件。示例:如果静态库包含a.obj
和b.obj
以及您将其链接到b.obj
但不是a.obj
的引用符号的EXE / DLL,那么a.obj
不会链接到可执行文件或DLL。但是,在重新阅读您的描述后,听起来并不像这里发生的那样。
答案 2 :(得分:0)
关闭功能内联。最简单的方法是在调试模式下编译。
在看到您的澄清后,编辑,我发现我的回答是错误的。也许如果你将函数的主体移动到.h文件的另一部分,使用“inline”关键字?
答案 3 :(得分:0)
抱歉,我应该澄清一下我正在构建调试模式,内联和所有优化都关闭。此外,代码在内联之前就被删除了,因为它甚至没有引用甚至被考虑用于内联。
答案 4 :(得分:0)
另一种选择是使用.inl文件根据您的构建在内联函数和非内联函数之间切换,如下所示:
在foo.inl文件中:
inline std::string Foo::ThisMethodDoesNotRun()
{
return "Not Running";
}
在foo.h中:
#if !COVERAGE_BUILD
#include "foo.inl"
#endif
在foo.cpp中:
#if COVERAGE_BUILD
#define inline
#include "foo.inl"
#endif