1

我将 VS2005 VC++ 用于非托管 C++。我有 VSTS 并且正在尝试使用代码覆盖率工具来完成关于单元测试的两件事:

  1. 看看我有多少被测试的引用代码正在执行
  2. 查看我的测试代码中有多少方法(如果有)根本没有经过单元测试

设置 VSTS 代码覆盖工具(请参阅链接文本)并完成任务 #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 文件中,并且代码覆盖率工具显示它根本没有被执行过。在大多数情况下,我希望编译器为我完成这种消除,但对于代码覆盖工具,它会破坏大部分价值(例如,寻找未经测试的方法)。我已经尝试了很多方法来告诉编译器停止对我聪明并编译所有东西,但我很难过。如果代码覆盖工具能弥补这一点会很好(我想通过扫描源代码并将其与链接器输出匹配),但我没有发现任何迹象表明它有一个特殊的模式可以打开。

在此先感谢克格勃

4

5 回答 5

1

确保您的函数不被丢弃的一种方法是导出它们。您可以通过添加__declspec(dllexport)到您的函数声明来做到这一点。最好将其包装在 C 预处理器宏中,以便您可以将其关闭,因为它是特定于编译器的,您可能不希望所有构建都导出符号。导出函数的另一种方法是创建一个.DEF文件

如果内联是问题所在,您也可能在__declspec(noinline).

您的代码是否在静态库中,然后编译成测试 EXE/DLL?链接器将自动丢弃静态库中未引用的目标文件。示例:如果静态库包含a.objandb.obj以及您将其链接到引用符号 from b.objbut not的 EXE/DLL a.obj,则其内容a.obj将不会链接到可执行文件或 DLL。但是,在重新阅读您的描述后,这听起来不像是这里发生的事情。

于 2008-09-20T06:51:29.910 回答
1

您可以尝试添加一行代码以仅在某些条件为真时调用该函数,并保证该条件永远不会为真。只要确保编译器无法解决这个问题。例如,


int main(int argc, char **argv)
{
  if(argv == NULL)  // C runtime says this won't happen
    someMethodWhichIsntReallyEverCalled();
}
于 2008-09-19T20:22:20.983 回答
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
于 2008-09-19T20:43:18.377 回答
0

关闭函数的内联。最简单的方法是在调试模式下编译。

编辑:看到你的澄清后,我发现我的答案是错误的。也许如果您使用“inline”关键字将函数体移动到 .h 文件的另一部分?

于 2008-09-19T19:52:26.703 回答
0

抱歉,我应该澄清一下,我正在使用内联和所有优化来构建调试模式。此外,代码甚至在内联发生之前就被删除了,因为它甚至从未被考虑过内联。

于 2008-09-19T20:05:02.883 回答