Category Archives: Unit Testing

The Terrible Truth About Version 1.0.0.0

Let me start by saying that if you think this going to be a post about how bad most “v1” software is then you will be sorely disappointed and you should move on.

What I am going to talk about is fairly similar to Scott Hanselman’s blog on semantic versioning and the reasons you should be using versioning in your software.

Care Factor

Firstly, you may ask yourself, “why should I care about versioning?”

This is a fair question.

Perhaps you don’t need to care about it, but I suspect more accurately you’ve never needed to care about it.

Through the custom software projects I’ve been involved in my career I’ve seen pretty much any combination you care to think of of how software can be built, released and maintained.  In the majority of cases proper versioning has taken a back seat to almost every other aspect of delivery (assuming versioning was even thought of at all).  Certainly the discussions I’ve often participated in around exactly what version was deployed where have tended to be fairly excruciating as they have typically arisen when there is a problem that needs root cause analysis and ultimately a fix.

Examples of bad practice I’ve seen are:

  • Using file create date / time to determine which assembly copy was newer (of course this approach was undocumented).
  • Someone screwed up the versioning so the newer builds had an older version number (and nobody ever bothered to fix it).
  • Everything is versioned 1.0.0.0 with a mix of “F5” developer machine builds and build server builds being deployed randomly to fix issues.  This one resulted in “race conditions” where an assembly may get updated from more than one source (and you never knew which one).
  • New build server = zero out all counters = ground-hog day versioning (or “what was old is now new”).
  • New branch, old version number scheme.  Builds with parallel version numbers. Oops.
  • Version 5 of ReSharper had assembly (and MSI) versions that bore a tenuous relationship to the actual official “version”.  The 5.1.2 release notes have an interesting responses thread which I would put as recommended reading on how versioning affects end users.

The bottom line is that versioning (when used properly) allows us to identify a unique set of features and configurations that were in use at any given time.  In .Net it also gives us access to one of the more powerful features of the Global Assembly Cache (GAC) as we can deploy multiple versions of the same assembly side-by-side!

If this seems self-explanatory that’s because it is.

Still With Me?

What I’ve written so far could apply equally to any technology used in software delivery but now I’m going to cover what I think is the root cause of the lack of care about versioning in the .Net landscape:

It’s too easy to not care about version with .Net.

Thanks to Microsoft we get a free AssemblyInfo file along for the ride in each new project we create.  It wonderfully provides us with this template:

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("YourApplicationName")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("YourApplicationName")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("1266236f-9358-40d0-aac7-fe41ae102f04")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

The problem is the last two lines. I wonder how many people bother to even look at this file?

Let’s try a little experiment – how many matches for the default entry for version in the AssemblyInfo file can we find on GitHub? Oh, about 62,000.

Now this isn’t necessarily a problem but it indicates the scale of the challenge! To be fair to those on GitHub, all/some/none of those matches may well be overridden on a build server (I hope so!) using one of the multitude of techniques available (if you’d like a few options let me know and I’ll do another post on this).

Let’s solve the problem by deleting those two lines – sounds like a plan? Get rid of the pesky version number completely.  Does the application still compile? Yup.

So what version do we get left with?  Let’s take a look at the resulting details.

You are kidding right?!

What The?! Version 0.0.0.0?!  We’ve made things even more broken than they already were.  That’s not a strategy!

Some Suggestions

Fairly obviously we are somewhat stuck with what we have here – it is not illegal at compile time to not have an explicit version number defined (resulting in 0.0.0.0).  We can’t modify the default behaviour of csc.exe or vbc.exe to enforce an incremented version number…

Assuming you’re using good practices and have a build server running your builds you can drop in a couple of unit tests that will allow you to ensure any compiled assembly doesn’t have either of our problematic versions.  Here’s a super simple example of how to do this.  Note this needs to run on your build server – these tests will fail on developer machines if you aren’t checking in updated AssemblyInfo files (which I would recommend against).


[TestMethod]
public void ValidateNotDefaultVersionNumber()
{
       const string defaultVersionNumber = "1.0.0.0";
       var myTestPoco = new MyPoco();
       var assembly = Assembly.GetAssembly(myTestPoco.GetType());
       Assert.AreNotEqual(defaultVersionNumber, assembly.GetName().Version.ToString());
}

[TestMethod]
public void ValidateNotEmptyVersionNumber()
{
       const string noDefinedVersionNumber = "0.0.0.0";
       var myTestPoco = new MyPoco();
       var assembly = Assembly.GetAssembly(myTestPoco.GetType());
       Assert.AreNotEqual(noDefinedVersionNumber, assembly.GetName().Version.ToString());
}

Remember to update the tests as you increment major / minor version numbers.

The goal is to ensure your build server will not emmit assemblies that have version numbers that match those held in source control.  We’re doing this to enforce deployment of server builds and make it obviously a different version number for a developer build.  I personally set builds to never check updated AssemblyInfo files back into source control for this very reason.

Make sure you *do* label builds in source control however.  If you don’t you may have challenges in the longer term in being able to retrieve older versions unless you have a very large “drops” storage location :).

Early on in planning your project you should also decide on a version number scheme and then stick to it.  Make sure it is documented and supported in your release management practices and that everyone on the team understands how it works.  It will also ease communication with your stakeholders when you have known version numbers to discuss (no more “it will be in the next release”).

Finally, don’t let the version number hide away.  Ensure it displayed somewhere in the application you’re building.  It doesn’t need to be on every page or screen but it should be somewhere that a non-Admin user can easily view.

So, there we go, hopefully a few handy tips that will have you revisting the AssemblyInfo files in your projects.

Happy versioning!

Dilbert.com

Tagged , , ,

Doing the Shimmy Fake (VS11 Beta Unit Test Isolation).

I’m sure many of you have read of or heard about the Moles Power Tool that shipped as an add-on to the original Visual Studio 2010 release back in 2009. There was certainly a lot of speculation about which way this Microsoft Research project would go.

The great news is that with the impending Visual Studio “11” release it appears the Moles Power Tool is now baked into the Microsoft.QualityTools namespace.

I first read about this on the MSDN ALM blog which I’d recommend you go and have a look at. My first thought was that the new Shim Fake is essentially what a Mole was previously. In writing up a few simple test cases my hunch was confirmed (see the tooltip reads “Sets the mole of…”:

fakemole

(I expect this will change before the RTM release though!)

So what can you do with a Shim? A Shim allows you to redirect calls to a method to a delegate you control which means you can control flow in tests that might otherwise have been blocked. Where I’ve used this heavily previously was with SharePoint 2010 classes and with the System.Configuration namespace.

You need to do a bit of work to create the baseline for a Fake – firstly the assemblies must be referenced in your Unit Test project in Visual Studio – right click on the assembly under “References” and choose “Add Fake Assembly”:

The Add Fakes Assembly context menu item.

Visual Studio will add some XML files that define the Fake and a new reference will appear that represents the Fakes:

Solution Explorer with Fakes.

A Simple Example

The easiest way to show how this all works in your favour is with a simple example. Firstly let’s assume we have a simple helper class that utilises System.IO.File. In the past we would have had to resort to 3rd party products to redirect any calls to System.IO.File so that we can test the code around the call. Here’s our File helper class definition:


public class FileWriter
{
     public void AppendContentsToFile(string filePath, string conentToAppend)
     {
         try
         {
             System.IO.File.AppendAllText(filePath, conentToAppend);
         }
         catch (Exception ex)
         {
             // log and throw.
         }
     }
}

And now let’s see how we use a Shim to allow us to test the FileWriter AppendContentsToFile method. The important elements to note are: using the Fakes namespace so that you can create a ShimContext which is needed to use a Shim. You’ll also notice that the Shim has a different class name and that the method combines the name and type of each parameter. If you don’t use a ShimContext your test will fail, but helpfully the test runner will actually provide a code sample of what needs doing in order to fix the test.

By using an anonymous delegate we provide a redirection of the call to a method we write and control. This quickly becomes a powerful way to isolate just your code from underlying Framework methods.


using Microsoft.QualityTools.Testing.Fakes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UnitTestingDemoApp;

namespace UnitTestProject1
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestFileWriterAppendContents()
        {
            using (ShimsContext.Create())
            {
                var writer = new FileWriter();

                System.IO.Fakes.ShimFile.AppendAllTextStringString = (file, contents) =>; AppendStringToFile(file, contents);

                writer.AppendContentsToFile("C:\\some\\path\\afile.text", "somecontents");
            }
        }

        private void AppendStringToFile(string filePath, string textToAppend)
        {
            // perform some logic, maybe throw exceptions.
        }
    }
}

This is a simple example of how Shims can be used – right now beyond MSDN there isn’t a lot of detail about but if you read up on Moles you will quickly get the idea.

And the Shimmy Fake? Well, I tip my hat to Australian kids entertainers the Wiggles and their Shimmy Shake from 2008…

Tagged , , , , ,