【问题标题】:Partial coverage of a return statement in C++/CLIC++/CLI 中的 return 语句的部分覆盖
【发布时间】:2011-02-16 21:43:22
【问题描述】:

我有 C++/CLI 代码,并且正在使用 Visual Studio 2008 Team Suite Code Coverage。

代码头:

// Library.h

#pragma once

#include <string>

using namespace System;

namespace Library
{
    public ref class MyClass
    {
    public:
  static void MyFoo();
  static std::string Foo();
    };
}

代码实现:

#include "Library.h"

using namespace Library;
using namespace System;

void MyClass::MyFoo()
{
 Foo();
}

std::string MyClass::Foo()
{
 return std::string();
}

我有一个 C# 单元测试,它调用 MyClass.MyFoo():

[TestMethod]
public void TestMethod1()
{
    Library.MyClass.MyFoo();
}

出于某种原因,我没有得到MyClass 的完整代码覆盖率。 Foo() 方法有 3 个未覆盖的块和 5 个覆盖的块。右大括号 (}) 标记为橙色 - 部分覆盖。我不知道为什么它被部分覆盖而不是完全覆盖,这是我的问题。

MyClass Code Coverage Print Screen http://img217.imageshack.us/img217/7664/myclasscoverage.png

更新

另一个例子:

标题:

// Library.h

#pragma once

using namespace System;

namespace Library
{
    struct MyStruct
    {
        int _number;
    };

    public ref class MyClass
    {
    public:
        static void MyFoo();
        static MyStruct* Foo();
    };
}

实施:

#include "Library.h"

using namespace Library;
using namespace System;

void MyClass::MyFoo()
{
    delete Foo();
}

MyStruct* MyClass::Foo()
{
    return new MyStruct();
}

我仍然在 Foo 的 return 声明中得到同样的缺失报道。

【问题讨论】:

    标签: visual-studio-2008 c++-cli code-coverage


    【解决方案1】:

    您没有涵盖函数通过异常而不是正常退出的情况。当然,如果您甚至不能构造一个零长度的std::string,那么您的程序可能已经无法恢复,但确定这超出了代码覆盖率分析的范围。

    编辑:为了提高覆盖率,您可以模拟一个全局 operator new,它基于您可以在测试用例中设置的一些全局标志(或更灵活地,在第 N 次分配时失败)失败。

    例如

    int allocation_failure = 0;
    void* operator new(size_t requestedbytes)
    {
        if (allocation_failure) {
            if (!--allocation_failure) {
                throw std::bad_alloc();
            }
        }
        void* retval = malloc(requestedBytes);
        if (!retval) {
            throw std::bad_alloc();
        }
        return retval;
    }
    
    void operator delete(void* p)
    {
        if (p) free(p);
    }
    

    或者您可以有条件地失败特定大小的分配,或特定大小的第 N 次分配等,以通过您的代码执行所有可能的路径。

    【讨论】:

    • 看我给出的第二个例子。它不使用 std::string。
    • new 的任何使用都可能因抛出异常而失败。您的测试用例未涵盖异常路径。
    • 我很怀疑,但你是对的。我设法创建了类似于我的第二个示例的代码,并通过使其抛出异常来完全覆盖它。我无法完全涵盖返回 std::string 的内容,但似乎我很难让它在所有可能的地方抛出异常。谢谢!
    【解决方案2】:

    [完全披露:我在帮助在 VS 中创建代码覆盖工具的团队中]

    尝试针对发布版本而不是调试版本收集代码覆盖率。

    在应用了某些优化/转换后,编译器可以发出实际上无法访问的 IL。查看是否是这种情况的最简单方法是使用 ildasm 或 Reflector 查看 IL。示例见here

    【讨论】:

    • 出于好奇(既然您在这里:-P),您是否知道(或者您能说)Microsoft 是否打算在任何时候支持原生 C++ 的测试和覆盖分析?我们 C++ 开发人员经常感到被冷落,所有令人敬畏的 Visual Studio 新功能都仅限于 .NET(尽管不可否认,本机代码分析器非常好)。
    • 我们收到了很多关于需要使用我们的工具更好地支持本机代码的反馈。我无法谈论本机测试的未来(这是一个不同的团队),但自 VS2005 以来,代码覆盖率一直适用于本机代码(如分析器)。体验不如托管的那么完美,但功能就在那里。请参阅blogs.msdn.com/ms_joc/archive/2005/10/04/477166.aspx 了解更多信息。
    • @Chris:非常感谢您提供的链接;我不知道这是一个可用的功能。在 Visual Studio GUI 中,您永远不会猜到支持本机代码覆盖率。缺乏内置的高亮支持令人失望,但覆盖率指标 + XML 格式输出 = 一个巨大的优势。太棒了。
    • 我已经尝试在发行版中编译它并运行测试。我仍然得到部分报道。我试过使用反射器,但它会为非托管 Foo() 方法抛出异常。
    • 全面披露:我在 Semantic Designs 创建测试覆盖工具的团队中。如果问题是“类型擦除”在插入测试覆盖仪器之前插入代码,那么您最终会得到某种效果。我们的工具在未经修饰的源代码上运行(例如,在类型擦除之前),因此您不应该得到这种特殊的工件。 (见semanticdesigns.com/Products/TestCoverage/CppTestCoverage.html)。
    猜你喜欢
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    • 2015-12-04
    • 1970-01-01
    • 2019-06-08
    • 1970-01-01
    • 1970-01-01
    • 2013-08-19
    相关资源
    最近更新 更多