Let’s Talk Unit Tests

What is it?

Unit testing is just what it sounds like; you programmatically test very small pieces of code (units) for specific results.
A unit test is code testing code that once written, can be ran over and over again to quickly test changes in environment or code. Code that is unit tested has very specific criteria that can be checked to determine if it is running properly and is isolated from other implementation code to narrow the identifiable problems that may cause a unit test to fail.

Unit tests in Visual Studio are simply classes in a Test Project that are integrated into the development environment for easy development and analysis of
code.

How do you use unit tests?

There are several ways to go about developing unit tests conceptually, and it depends greatly on the goal of your unit tests as well as the development culture/style that you participate in. Very large organizations use unit testing
much differently than smaller shops because they generally have more procedural policies as well as a deeper pool of resources to dedicate specifically to unit testing. In smaller shops, unit testing may be done by the original developer of the application which some organizations are strictly against. The benefit of splitting the work between developers or developer groups is that it provides either the developer specific scenarios to satisfy, as in the case of red-green development; or the unit tester the ability to check the developers work for bugs they may not have been aware of.

I use unit tests primarily either in parallel current development or immediately after because I use
unit tests to verify the work that I've done, as well as prepare for how the application responds in the future when a change or enhancement has been made.

Once the unit tests are written, I run through all of them and check how successful they are. When I notice one that has failed or proved inconclusive I investigate why the failure occurred and can generally pinpoint the offending code fairly swiftly.

You can see below the test results of a list of unit tests that have ran inside Visual Studio for one of my projects.

Unit Test Results

Getting Started

In Visual Studio, you can either create a new Test Project and add Unit Tests to the project, or right click on a function you have created and click Create Unit Tests… This will bring up a list of functions to create unit tests for, select the ones you are interested in and begin.

Personally, I prefer creating my own Test Project, and adding unit tests manually. It’s not quite as automated, but I get exactly the
setup of the test I want with none of the fluff added during automation.

How do you write a unit test?

Writing unit tests are as easy or complex as you want them to be, but it as almost always better to lean towards simplicity. Remember, unit tests by nature should only test a single unit of code and should each have identifiable pass/fail results. Let’s look at some examples and discuss the pro’s and con’s of the approach taken in these examples.

First, we’ll write a simple test to check the retrieval of a single entity based on ID. This is a pretty common action when working with data. Specy is a Linq2SQL entity in my project, so don’t let that throw you off at all.

[TestMethod]
public void GetSpeciesTest()
{
    Specy results = null;
    int speciesID = 1;  //a valid speciesID

    results = TSDLC.GetSpecies(speciesID);
    
    //Check if null
    Assert.IsNotNull(results);

    //Check that species ID returned is species ID supplied
    if (results.SpeciesID != 1)
    {
        Assert.Fail();
    }
    
    //Todo: add any additional checks on the data being returned

    //Check that the species returned is null when not found
    speciesID = 0;  //an invalid speciesID
    results = TSDLC.GetSpecies(speciesID);
    
    Assert.IsNull(results);
}

First, when you set up a unit test, you need to specify (manually) all of the inputs that your testing function will need; in this case we’re providing a known good speciesID to look up the Specy. Obviously if someone deletes this record then this unit test will fail, so we know as a pre-requisite, this record in the database must exist. Next, we call our function we want to test to retrieve the Specy. If anything within that function throws an unhandled error, the unit test will fail (which is good to know). From here, we can test the result to see if it is as we expect. For demonstration, I’m checking if the ID of the returned Specy does not match the ID provided then we know the function failed to return the data we expected.

Assert.Fail(), simply notifies the test that it has failed and can be called anytime you feel the test has failed.

At this point, a purist would say that’s it; any more information would justify creating a seperate unit test. I, on the other hand, prefer to consider other situations that test the validity of this function as part of this unit test. Please note, this is a personal preference and there are pro’s and con’s to doing so.
Pro is that I believe it’s more manageable than to have such a huge number of unit tests to manage and create as well as conceptually if it fails at any point while trying to do such a basic function, in my mind, the unit as a whole failed. Con is it can be ambiguous without debugging/investigating further exactly which aspect of the test failed, in this case, did it fail in the function call itself, in analysis of the returned result, or when we passed in an empty speciesID.

The last part, check’s what happens when things don’t go as planned, such as passing in an invalid speciesID, does it return back null as we expect, or does it blow up (or perhaps return back a legitimate Specy we didn’t expect – and didn’t want).

A slightly longer example

Here is an example of a slightly more detailed unit test, which creates a new record and then checks to ensure the database creating all of the fields in the record with the data that was passed to it. After it is finished, it calls a delete function to clean up the newly created entry to avoid having entries from unit tests left in the database.

[TestMethod]
public void CreateRecordTest()
{
    //init results default
    int results = 0;
    
    //setup variables for test
    int userID = 1;
    decimal latitude = (decimal)26.2341;
    decimal longitude = (decimal)-81.1234;
    DateTime recordedDate = DateTime.Now;
    string name = "UnitTest";
    string description = "UnitTest - Please delete.";
    decimal quantity = 1;

    //create record
    results = TSDLC.CreateRecord(userID, latitude, longitude, recordedDate, name, description, quantity);

    //results = id, check if valid
    if (results <= 0)
    {
        Assert.Fail();
    }

    //Load record and make sure it has same values as entered
    Record record = TSDLC.GetRecord(results);

    if (record.UserID != userID)
    {
        Assert.Fail();
    }
    if (record.Latitude.Value != latitude)
    {
        Assert.Fail();
    }
    if (record.Longitude.Value != longitude)
    {
        Assert.Fail();
    }
    if(record.Recorded.ToShortDateString() != recordedDate.ToShortDateString())
    {
        Assert.Fail();
    }
    if(record.Name != name)
    {
        Assert.Fail();
    }
    if(record.Description != description)
    {
        Assert.Fail();
    }
    if(record.Quantity != quantity)
    {
        Assert.Fail();
    }
    
    //Cleanup (and test delete record)
    TSDLC.DeleteRecord(results);
}

Using the Test View in Visual Studio

Test View

Once all of these tests are coded, you’re going to want to run them. To run several unit tests at a time you can use the Test View panel (pictured right) in Visual Studio by clicking Test > Windows > Test View. After running the tests the Test Results panel should appear (pictured above), to show you the outcome of each test ran.

Hope this was helpful, and as always please feel free to leave comments about this post below; I look forward to knowing if readers agree, disagree, or have additional suggestions for working with Unit Testing in Visual Studio.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s