Testing your .NET code without paying a gazillion dollars for analysis software - Part 1: Unit Testing

 For years, I was among the vast collection of .NET developers that didn't really test my code.  "Works on my machine," I'd say.  The mention of unit tests to many devs often resulted in either a blank stare or a diatribe on "it takes too much time," blah blah.


Budgetary concerns and deadlines aside, one very good reason to test is simply to improve your skill as a programmer.  There are a number of ways to do that - pair programming, code reviews, static analysis, the list goes on.  Unfortunately, I've talked to far too many developers that simply weren't interested in improving their craft.

Note: I'm not counting Visual Studio within the 'gazillion dollars' category, as most .NET devs have access to some version of that. I'm also using Visual Studio Premium 2013 for my examples.

Let's start with the baseline: unit tests.  If you're unfamiliar with unit tests, Wikipedia describes them as "a software testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures are tested to determine if they are fit for use."

Visual Studio has a built-in test framework, but there are several to choose from.  I've used MSTest (the one built-in) and NUnit.  Personally, I like NUnit; it's free and can be run outside Visual Studio as well.  Here's how to get started.

Create a new application in Visual Studio.  For purposes of this demonstration, I'll use a console app:


Clicking OK creates my solution and app.  Right off the bat, I'll add a project to hold my tests.  Since I'll be using NUnit, I want a Class Library project:


Once my projects are there, I need to make sure the required tools/dependencies are installed.  For that, I use NuGet by going to Tools > NuGet Package Manager > Manage NuGet Packages for Solution.  I install the NUnit framework/adapter combo as well as the Runners package.


Next, I add a reference to my primary project TestingApplication.Console and rename the default test class from Class1.cs to SampleTests.cs.  I'm almost ready, but I don't have any code yet.  At this point, I can do one of two things - I can write some code and then test it, or I can write tests first - following the tenets of test driven development (TDD).

For this, I create a new method to test, but write my test first before writing my implementation:

In my main app:

public static int MultiplyTwoNumbers(int firstNumber, int secondNumber)
        {
            throw new NotImplementedException();
        }

In the test class:

using NUnit.Framework;
using TestingApplication.Console;

namespace TestingApplication.Tests
{
    [TestFixture]
    public class SampleTests
    {
        [Test]
        public void MultiplicationWorksProperly()
        {
            var product = Program.MultiplyTwoNumbers(5, 5);
            Assert.AreEqual(product, 25);
        }
    }
}

A couple things to call out here.  First - I had to make my application class public for my test class to see it (console apps are private by default).  I also needed to include references to the NUnit.Framework and TestingApplication.Console namespaces in my test class.  The attributes TestFixture and Test are used by NUnit to know how to read and run your test.  More information on writing tests is available on the NUnit site.

At this point, if I right click my TestingApplication.Tests project and select "Run Unit Tests" I get an expected failure:


Now it's time to write code that isn't a test.

I remove the exception and add the following statement to my MultiplyTwoNumbers method:

public static int MultiplyTwoNumbers(int firstNumber, int secondNumber)
        {
            return firstNumber + secondNumber;
        }

I run my test again, and it promptly fails.  I went too quickly and added the numbers instead of multiplying them.


I adjust my code accordingly:

public static int MultiplyTwoNumbers(int firstNumber, int secondNumber)
        {
            return firstNumber * secondNumber;
        }

Running the test one more time produces a result of Success.

Once the framework is set up, it becomes very straightforward to write a quick test to prevent an issue from happening again or as a benchmark for code not yet written.  Unit testing doesn't replace solid functional testing, but it will catch unnecessary mistakes and produce a better quality product.

In Part II, I'll talk about other tools to analyze your code.

Popular Posts