Unit testing – first steps

By Craig Rowe on

We’re all testing right? and I don’t just mean ‘it works on my machine’ or ‘clicking around a bit’… ok well I do mean that but also more.

There’s no way you’ve not heard of ‘unit testing’ so I won’t labour the point. What we’re talking about here is confirming through tests the functionality of your code at the smallest appropriate level. Now that level varies depending on the specific piece of code you wish to confirm. You don’t want to get to the point where your tests are merely confirming that the language you are using works at a statement level but equally you don’t want to be running automated tests that make three database calls and render a view.

Now although you will have heard of it you may not have done it. There are plenty of resources and blogs out there both on Unit Testing and Test Driven Development but this post aims just to give you a flavour of how you might start down the unit testing road.

ServCheck

A recent project we did works well as a case study of where you can start with your unit testing. ServCheck is an online surveying application. The important thing about it, with regard to this post, is that it has a very well defined payment and quota model (surveys are run within organisations and require a certain quota of responses to be valid).

The reason I highlight these two aspects is because they have very specific small-scale logic that has to be correct. This is where I think it becomes easy to get into Unit Testing. It’s hard to jump straight into TDD, its similarly hard to apply tests to a highly coupled legacy codebase, but to test small algorithms… well that should be easy.

The low hanging fruit of Unit Testing

In my opinion this is the low hanging fruit of unit testing. It’s easy to come up with the tests and at the same time easy to rationalise the time spent on it to even the most sceptical of managers and clients. The classic “we don’t have time to test”, wrong as it may be, is far simpler to argue against when we’re talking about rule based systems or algorithms.

So let’s take for example a cost calculation on ServCheck. Now, ICS provides its ServCheck services primarily to it’s members. Memberhips come in different flavours and with different entitlements. For example a Council receives its first ServCheck survey each year as part of its annual membership rather than paying separately. This means that in our system if a ServCheck coordinator from an approved member council signs up for a new survey, and they’ve not done any that year, they get it ‘for free’.

The structure of the test

I’ve become used to the three step name approach of tests. That is to say that method names are split into three parts (although I’ve recently become quite keen on the style discussed by Phil Haack on his blog). The three part test name is inspired by Roy Osherove. He uses test names like [MethodName_StateUnderTest_ExpectedBehavior]. As you can see in the test below I’ve gone for a similar style:

[Fact]
public void ServCheck_CouncilMemberNullSurveys_TreatAsFirstFree()
{
	// Arrange
	var service = GetServCheckService();
	var company = new Company { IsMember = true, Type = (int)CompanyType.COU };

	// Act
	var price = service.GetPriceValue(company);

	// Assert
	Assert.Equal(0, price);
}

The above test is a direct snippet from the ServCheck project. On this project I’m using xUnit as my test library which is where the ‘Fact’ attribute comes from (which is picked up by test runners like TestDriven.Net or xUnits own runner). I’ve added the ‘Arrange/Act/Assert’ comments into the snippet to illustrate the layout of the test code. AAA is a rather widespread method for ensuring consistency within your tests.

The ‘GetServCheckService()’ method is what some may describe as the ‘Build Up’ part of the test. The actual function is a little helper that returns a ServCheckService (the service class that contains methods to do with costing surveys). This service contains no dependencies (such as database repositories etc), although if it did they would be mocked to avoid testing too much in one test. A brand new company instantiated like this obviously has no surveys (although this would be subject to confirmation via another test). Therefore the ‘state under test’ is a council with null surveys. The expected result is that the price for a survey is ‘free’ or ’0′. No exception is expected (that would be Assert.Throws).

The Assert class provides a number of methods that essentially return true or false – equating to a test pass of fail. In this case we are just checking that the price value equals 0.

Note: In this case the method being tested (GetPriceValue) is completely in code/logic – essentially a bunch of ifs etc. If it would more complicated, for example relied on a database, we might consider refactoring it or passing it mock objects so it could be more easily tested in smaller chunks.

Running the tests

As mentionned earlier TestDriven (a plugin for Visual Studio) is one way that tests can be run, another is the xUnit GUI runner that allows you to open a DLL with tests and run them to see the results. You could, if you wanted to, just create your own application that specifically runs the tests although that’s probably unecessary with the tools available to you.

At Headscape we actually run continuous integration on our development environment (probably a topic for another post). So when we check in a build is forced and our dev website is immediately updated. All well and good. The nice thing about that is it can also run our tests for us. Our process is then, run tests locally, commit, see build and tests run on remote clean build server. Managers can then see what tests currently exist and if they were successfull.

Running tests on Build

To do this I hooked up our build server to the xUnit runner and results templates. Now when a build runs on our build server we get the following on a website:

In fact I’d go so far as to say this was readable enough output that it could be used in communication with clients when confirming that your implementation, as defined by your tests, is correct.

In closing

I hope if you’re not already doing it that this post gave you a little insight into how you might get started, particularly with the low hanging fruit of unit testing. The approach I’ve described here is very much confirmation of code as opposed to creation (TDD) which I think is a much easier thing to get to grips with first before moving on to more advanced techniques.

I touched on a few techniques from naming conventions and AAA through automated builds and TDD I urge you to follow through on a few of the links and see how you feel about each one.

Sources

XUnit – https://xunit.codeplex.com/
Roy Osherove – Art of Unit Testing

One Comment

Add a Comment

* Required
* Required