Linq To NCover Part 2

I can’t begin to explain how excited I get when working with Linq. Until now, there were times that you needed to write a large amount of code to do the same basic operations like determining a child object had certain properties set, or determine the count of how many times a property is set to true.

 

You would have to declare a bunch of variables like “bool found;” and then you would perform a foreach loop on your objects, checking for certain conditions. Since you did the same thing over and over, you would go and find a code block that was close and modify it to fit your needs. Now there is a much more precise, easy to read syntax to perform the basic crud tasks, and they call it Linq.

 

With the power of Linq, you no longer have to write long winded code to walk all the items in a collection only to realize two or three of the twenty items are valid. You can now filter or select the objects that you would like to work with, with straight forward query syntax.

 

NCover stores the coverage file in an xml document. In that document is all the information needed to determine what classes are in a namespace, what methods are contained in a class and so forth. You can think of these as relationships or “joins”. Once this information is loaded into memory, you could perform a foreach loop against every single class in every single namespace until you found a match or you could query the data for exactly what you are looking for.

 

A typical query against an NCover coverage file could look like this:

CodeCoverage
c = CodeCoverage.Load(file);

var
retVal =from mod in c.Modules
            from cls in mod.Classes
            from method in cls.Methods

            where method.Name == ".ctor"
            select method;

In the above example each collection is aliased with a name, which can be used in the where clause with full Intellisense. You could easily add an additional where statements to only find .ctors (constructors) in a class that start with “GCheckout”. This syntax would look like this:

CodeCoverage
c = CodeCoverage.Load(file);

var
retVal =from mod in c.Modules
            from cls in mod.Classes
            from method in cls.Methods
            //only list classes in the GCheckout Namespace
            where cls.NameSpace == "GCheckout"
            where cls.Name.StartsWith("Request")
            where method.Name == ".ctor"
            select method;

You may notice that there are multiple instances where clauses in the Linq query. You could have just as easily replaced the second where keyword with && (in c#). I personally feel it is easier to read the intention of the statement by spelling out where on every “filter”.

 

My thought was the majority of people were going to want to perform queries against the classes and methods. I rolled up all the classes and methods on the CodeCoverage class in order to remove the need to reference the relationships between the modules and the classes and the methods.


CodeCoverage c = CodeCoverage.Load(file);

var retVal =from method in c.Methods
            from param in method.Parameters
            where param.FullType == typeof(decimal).ToString()
            orderby method.Name
            select method;

Download the sample code and tell me what you think.

LinqToNCover.zip (94.82 kb)

The next article will talk about how a Linq query was used to calculate the return value of a property.

kick it on DotNetKicks.com


Posted by: joe.feser
Posted on: 2/27/2008 at 2:51 PM
Tags: , ,
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (442) | Post RSSRSS comment feed

Linq To NCover Part 1

Back in August of 2007, I was assigned an enhancement request for the .Net sample code to integrate with Google Checkout. The enhancement stated that we only had 31% code coverage and we needed to improve our code coverage to 50%. The tool used to determine this code coverage was NCover.

 

I started playing around with it and was quickly able to realize what sections of the code had never been tested. We wanted to put more faith into our customers that our implementation was production quality so I spent the next week, after work, refining the unit tests until I obtained almost 70% code coverage.

 

After using the tool for a few days I realized that there were a few patterns throughout my code: The first one was I was writing code for conditions that never had test cases;

The other one was my overloaded constructors were rarely tested - Why would I test them, they should just work right?

 

Using the NCoverExplorer tool, I quickly began to notice that my branch coverage was on the weak side. I was able to visually see the exact reason why my code was not fully tested, my unit tests were only accounting for a few of the conditions that the code segment was meant to process.

 

Once you run NCover against your code, a coverage file is generated containing a large amount of very useful information, including the assemblies, namespaces, class names, the methods of those classes and the sequence points (enterprise version only). All of this information is stored in an xml document that can be reloaded for additional analysis.

 

One day I was sitting around trying to think of a sample project to build using some of the really cool new C# 3.0 language features and I thought to myself, ‘why not create a way to query the NCover coverage file using Linq’. You have to admit, it would be really cool to be able to find all methods in your application that take in a decimal data type or find all the methods that take a parameter with the name of description.

 

So I sat down one evening and looked at how I could make the information in the coverage file friendlier to search. I did not want to take the Linq to Xml approach at this time.  I enhanced the output of xsd.exe to support generic lists instead of arrays. Then I visited the coverage data and link up all the parent child data to allow people to file all methods that are contained in a class called “foo” that take in a string as a type.

 

Imagine being able to search all your code for all methods that are not constructors, and that have at least one parameter of type decimal. This is an example of how that statement would look using Linq To NCover:


CodeCoverage
c = CodeCoverage.Load(file);

var retVal = from method in c.Methods
from param in method.Parameters
where method.Name != ".ctor"
&& param.FullType == typeof(decimal).ToString()
orderby method.Name
select method;
 


Over the next few days, I will continue to expand this article to include releasing the source code.

 

As a side note, NCover is such a great tool; I am moving to Greenville, SC next week to begin working for this amazing company.

 

More to come

kick it on DotNetKicks.com


Posted by: joe.feser
Posted on: 2/27/2008 at 5:30 AM
Tags: , , ,
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (99) | Post RSSRSS comment feed