Patrick Ramser
Patrick Ramser

Reputation: 46

OpenCover not generating coverage results on sealed classes

I've been working on implementing OpenCover in a local build of some of the various APIs I work on for the sake of getting a decent testing report structure built for my team. When attempting to run the coverage against my NUnit tests however I've discovered that some of my more important classes are omitted from the report generated and have the visited node for the respective object set to false.

I still receive the proper NUnit results and know that the coverage results I expect are there due to running against Visual Studio's built-in tool to validate also. It's just OpenCover that fails to report correctly.

The common thread in any of these objects going unreported as I've discovered appears to be that they're sealed. I'm guessing that OpenCover is skipping those classes and uses some type of reflection for it's reporting structure, but I haven't had a chance to check out the source to prove this since I'm on a pretty stringent, internal network.

Anybody run into anything similar or have any tips to overcome this issue? I, of course, can't just remove the sealed keyword from my classes since they need it.

Edit* Here's an example I wrote up of something similar:

using System.Text;
using NUnit.Framework;

namespace OpenCover.Sealed.Test
{
    using Helpers;

    [TestFixture]
    public class UtilityTest
    {
        [Test, Owner("Patrick Ramser")]
        public void ConcatTest()
        {
            Utility utility = Utility.CreateNewUtility();

            string concatMsg = utility.Concat
                ("1:{0} 2:{1} 3:{2}", "FIRST", "SECOND", "THIRD");

            Assert.AreEqual
                (concatMsg, "1:FIRST 2:SECOND 3:THIRD", "Wrong message returned!");
        }
    }
}

namespace OpenCover.Sealed.Helpers
{
    public sealed class Utility
    {
        internal Utility()
        {

        }

        public static Utility CreateNewUtility()
        {
            return new Utility();
        }

        public string Concat(string message, params string[] lstStrings)
        {
            StringBuilder builder = new StringBuilder(message);

            for (int i = 0; i < lstStrings.Length; i++)
            {
                builder.Replace("{" + i + "}", lstStrings[i]);
            }

            return builder.ToString();
        }
    }
}

When using both NUnit and the new test assembly I simply reference:

D:\exes\OpenCover\OpenCover.Console.exe
-target:"D:\TestRunners\nunit.console.exe"
-targetargs:"/nologo /domain=Single /xml=C:\NUnit\Artifacts\nunit-results.xml
D:\OpenCover.Sealed.Test\bin\Debug\OpenCover.Sealed.Test.dll"
-output:"C:\NUnit\Artifacts\coverage.xml"
-register
-filter:"+[OpenCover.Sealed*]*"
-returntargetcode

There are no spaces or formatting for the batch script I run, I just limited it between lines to make it more readable.

Could internals either pose any issue?

Upvotes: 0

Views: 1389

Answers (1)

Patrick Ramser
Patrick Ramser

Reputation: 46

I believe I may have figured out my problem. The issue didn't end up being the sealed classes, rather that those classes weren't being used correctly with NUnit & the tested library.

I pulled all my resources to the same directory & changed NUnit to run in no app. domain (using the /domain=none argument) & that appeared to solve my problem. I'm guessing the fact that my custom NUnit code creates another app. domain & most of my test libraries live in disparate locations was causing some disconnect between the running code OpenCover needs to execute against.

The bad results I received (that I discovered now) were coming from my custom runner only being run through OpenCover which doesn't touch any of my sealed objects. I wasn't even using the test libraries the way it was set-up. Really sorry for the misunderstanding, Shawn! The coverage report works great & the results are now exactly what I needed.

Upvotes: 0

Related Questions