Partial coverage of the return statement in C ++ / CLI
I have C ++ / CLI code and I am using Visual Studio 2008 Team Suite Code Coverage.
Code header:
// Library.h
#pragma once
#include <string>
using namespace System;
namespace Library
{
public ref class MyClass
{
public:
static void MyFoo();
static std::string Foo();
};
}
Code implementation:
#include "Library.h"
using namespace Library;
using namespace System;
void MyClass::MyFoo()
{
Foo();
}
std::string MyClass::Foo()
{
return std::string();
}
I have a C # unit test that calls MyClass.MyFoo()
:
[TestMethod]
public void TestMethod1()
{
Library.MyClass.MyFoo();
}
For some reason I am not getting full code coverage for MyClass
. The Foo () method has 3 unclosed blocks and 5 closed blocks. Closing curly braces ( }
) are marked in orange - partially covered. I have no idea why this is partially covered and not fully covered and that is my question.
MyClass coverage print screen http://img217.imageshack.us/img217/7664/myclasscoverage.png
UPDATE
Another example:
Title:
// Library.h
#pragma once
using namespace System;
namespace Library
{
struct MyStruct
{
int _number;
};
public ref class MyClass
{
public:
static void MyFoo();
static MyStruct* Foo();
};
}
Implementation:
#include "Library.h"
using namespace Library;
using namespace System;
void MyClass::MyFoo()
{
delete Foo();
}
MyStruct* MyClass::Foo()
{
return new MyStruct();
}
I still get the same lack of coverage in the Foo statement return
.
a source to share
You are not covering the case where the function exits due to an exception instead of the normal one. Of course, if you can't even plot zero length std::string
, then your program is probably too far gone to recover, but defining this question is beyond the scope of code coverage analysis.
EDIT: For better coverage, you can concatenate a global operator new
that fails based on some kind of global flag (or more flexible, a failure on the Nth distribution) that you can set in your test case.
eg.
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);
}
Or you can conditionally deduce a specific size selection or Nth selection of a specific size etc. to implement all possible paths through your code.
a source to share
[Full disclosure: I'm on a team that helps build code coverage tools in VS]
Try to collect code coverage for release build instead of debug build.
The compiler may emit IL that is actually not available after applying certain optimizations / conversions. The easiest way to see if this is the case is to look at Il with ildasm or Reflector. See here for an example.
a source to share