Tuesday, February 13, 2007

NCover Setup - Part II

Following up on my previous post, I'm continuing to set up code coverage in my .NET 2.0 project with some specific criteria.

Kudos to Grant Drake (aka Kiwidude) who is very committed to the cause. I spent some time on his site last night, pouring over some of his FAQ. He left a comment on my blog earlier, citing an FAQ that I missed on his site. Plus he recommended version 1.5.4 of NCover instead of the latest 1.5.5beta. Good stuff!

So to follow through on my previous post.

The first thing I did was move my test namespace and their classes into a separate ClassLibrary. This included all the standard stuff:

  • remove the reference of NUnit from the Core library
  • add an NUnit reference to the Test library.
  • add a Core Library reference to the Test project.

After a quick compile, I dropped down to a command prompt and executed the same statement, except this time I had to specify the name of the Test harness assembly:

ncover.console nunit-console Test.dll //a Core

This worked and ...satisifies my second objective! The added bonus is now the coverage report only contains information about the Core namespace. This is great, but as an aside, since nothing has changed in the code I wonder if this is a bug in the "//a" switch? Update: The //a switch is for assemblies without their extensions, not namespaces.

As a further refinement, I can begin to take advantage of NUnit's Project capabilities. This enhancement simplifies things greatly. It allows me to:

  • test/cover multiple assemblies at a time
  • shield my build script from having any knowledge about the test harness configuration.
  • specify where to locate the configuration file (this should solve my third objective)

To create the Nunit project file:

  • open the NUnit-Gui and choose "New Project". I like to save the nunit file at the root of my solution.
  • add in the assemblies that contain your test fixtures. In my case, I have to specify the relative path to my Test Harness: /Test/bin/Debug/Test.dll

As an NUnit project file is simply an xml file, my nunit project file contains the following:

<NUnitProject>
  <Settings activeconfig="Debug" />
  <Config name="Debug" binpathtype="Auto">
	<assembly path="Test\bin\Debug\Test.dll" />
  </Config>
</NUnitProject>

With this in place, I can now generate my coverage report at the command line with the following statement:

ncover.console nunit-console TestProj.nunit //a Core

So far, this pretty good. The second objective was fairly easy, and although I've violated my first objective, Kiwidude has suggested this might be something I could correct with part of the build script, so I'll get to that soon enough.

Tomorrow, I'll tackle my third objective of being able to resolve configuration settings.

Monday, February 12, 2007

NCover Setup - Part I

About a year ago, one of my projects established some best practices for test-driven development where we found our sweet spot using .NET 1.1, NUnit, NCover and NCoverBrowser. Things were going great until one day, NCover stopped producing coverage reports. Despite my best efforts, I couldn't get it working again. Panic. Frustration. Pain. Despair. Acceptance: no more coverage reports....

Now, a new project is about to take off, this one using .NET 2.0, and I'm determined to get NCover running on this project. Problem is, documentation for NCover is still no where to be found online, only mixed messages in their forums.

So, for my reference, and potentially yours, I thought I'd share how I set this up. As I'm building an application for an enterprise the requirements can get pretty complex... here's what I'm shooting for:

  1. I typically structure a project so that I have a solution folder which contains copies of all the libraries my project will require to compile. I also bundle third-party tools with the solution folder so that when a developer checks the project out of source-control, the build script has everything it needs to operate without any configuration on behalf of the developer.
  2. I want to structure the solution so that the application code and the test harness are in different assemblies.
  3. In addition to separate test and application assemblies, configuration settings from the application code must be used with the test harness.
  4. I need to drive the code coverage from a NAnt script
  5. I need to integrate the output into CruiseControl.NET

So I downloaded NCover 1.5.5 beta and cracked open a new ClassLibrary project to simulate code coverage. I wrote two classes: a simple class "Core.Class1" and a test fixture "Test.Class1Test". I compiled the solution, dropped to a command prompt and manually tried to execute ncover using relative file paths. "Unable to locate file" errors.

As soon as I put both NCover and NUnit file paths into my PATH environment variable, the error messages started to change. The following statement, executed from the "bin\Debug" folder of my project:

"ncover.console nunit-console Core.dll //a Core"
...worked!

Although adding PATH variables violates objective #1 it did produce a coverage report for the Core and Test namespaces. Since my NUnit test cases are guaranteed to be 100% covered by NUnit, I'll need to find a way to exclude the Test namespace from the report.

I'll reorganize the project into separate assemblies and see how that changes this configuration tommorrow.

Read part two: NCover Setup - Part II

Friday, February 09, 2007

VB.NET Logical Operators are lame

While writing some application architecture documentation for my current project, I drew a blank looking for the technical term "short-circuit" logical operators.

These are really simple in C#.

public bool Method1()

{

   Console.WriteLine("Method1 called.");

   return false;

}

public bool Method2()

{

   Console.WriteLine("Method2 called.");

   return true;

}

public void ShowShortCircuiting()

{

   Console.WriteLine("Regular AND:");

   Console.WriteLine("Result is: {0}", Method1() & Method2());

   Console.WriteLine("Short-Circuit AND:");

   Console.WriteLine("Result is: {0}", Method1() && Method2());

}

Produces the following output:

Regular AND:
Method1 called.
Method2 called.
Result is: False
Short-Circuit AND:
Method1 called.
Result is: False

The concept is really simple too: If the first item isn't true then don't bother executing the next condition.

When speaking with a colleague, he asked if this was possible in VB.NET. Google says yes. But isn't syntax in VB is completely backward??

The C# equivalents map to VB.NET, thusly:

C#: &
VB: And
C#: &&
VB: AndAlso

To quote the article I've highlighted:

If you want the second test to be executed every time, use And. If that's not what you want, use AndAlso.

Syntax-wise, I think that this reads as: "I want this and also this to be evaluated". But if the first condition doesn't pass, (insert smirk) wouldn't it better to say, "I want this, and maybe this to be evaluated."??

I'm not sure what prompted me to switch from VB6 to C#, but boy, I'm glad I did.

Friday, February 02, 2007

Eating dog food I preach

There's a fairly large disconnect between what I personally use and what my industry has highlighted as holy-grail great. So I finally got around to creating a del.icio.us account, and managed to find the time to add it to my blog. (I found a great resource for a list of online-del.icio.us tools here)

While I'm not convinced I need the social-networking aspect, an online bookmark solution makes sense for a few reasons:

Too many browsers. I use FireFox for my day-to-day, but occasionally I'll encounter some weird bugginess in FireFox 2.0 so I'll boot up IE 7. What's interesting about switching back and forth between browsers is that once you get settled into a session with a half-dozen tabs open, you don't want to switch back during that session. I also find that I don't bookmark most pages, I use the Browser History sidebar (CTRL+H) to relocate helpful sites. An online solution makes a lot more sense; I just have to bookmark more frequently.

Obsessive Compulsion Disorder and Format C Colon Slash Syndrome. If I kept an organized list of links from the time that I started out online it would be several reams thick. Unfortunately, I never keep a list of bookmarks for too long because I start to suspect my windows machines with performance and garbage in the registry after the install is over a year old. (I start to get anxi around the six-month mark...) I tend to give into this paranoia and format my drives somewhat frequently and in doing so I always forget to backup my bookmarks.

Blog-worthy, maybe. I started my blog to capture thoughts and findings on the web, but some days, posting a blog entry is a challenge. While I do use my blog to capture URLs for reference, not all URLs are blog worthy.

...and heck, if a colleague wanted to find a URL that I found useful, I could point them to my del.icio.us account. So, maybe I do want the social aspect after all. Hmm.

Well, let's see how this experiment plays out -- I've added the delicious tag cloud to my blog on the right. If it's not there in a few months, maybe I stopped using it.