Unit Testing Basics

October 23, 2015 - .NET, Programming

It should not come as any sort of surprise that verifying that software works properly relies quite heavily on testing. While in an academic environment, it can be possible to prove that an algorithm will always work in a certain way, it is much more difficult to prove the same assertions with a piece of code implementing that algorithm; even more so when we consider the possibility of user interaction, which adds a arbitrary variable to the equation.

When dealing with large or complicated projects, testing needs to be done in layers. In addition to testing by using the same interface as the user and ensuring it all acts as expected, it is also reasonable to add code-level tests. These tests will run functions and methods or use classes within the program(s) and verify that they work as intended. This can be used quite fruitfully in combination with normal testing to identify regressions easier.

Some languages, such as D, include built-in, compiler/language-level support for Unit Tests. In D you can define a Unit Test within the block that you want to test, usually it is tied to a Class instance, as shown in the documentation examples.

The D Programming Language Logo

The D Programming Language Logo, Which I’ve inserted here for no particularly salient reason.

Different languages, platforms, and frameworks will tend to do tests differently. Most languages and platforms don’t have the sort of Unit Test functionality we see in D, but as the industry has matured, and particularly with design concepts like test-driven development being pushed to the forefront, most development platforms have either had Unit Test functionality added to them by third parties, or had it added as an integral component.

Unit Test Projects

In Visual Studio, Unit Test Projects can be added to a solution. Test Classes and Test Methods are added to that project, and they can reference your other projects in order to test them. This is a particularly good approach for testing libraries, such as BASeParser. BASeParser is a relatively straightforward recursive descent Expression parser/evaluator, which was one of my first C# projects, which I had based off of a VB6 library of the same function and name. This is actually a very straightforward thing to test; we can have a test method merely have a set of expressions and the expected result, and verify that evaluating that expression provides the expected value:

By running a test- or integrating a test into your build process- you can have the new version of the program verified to provide correct results. If you rewrite a critical part of the program to improve performance, you don’t want to make the results wrong- having these sorts of checks and balances in place can let you know right away if a commit you made has just caused regressions, or broken expected behaviour. You can run these tests directly from the IDE, which is a very useful feature. A small marker appears next to the Method header, and you can click it to get test options- run the tests, run all tests in a class, debug tests, etc. The Debug capability is particularly valuable, as it can help you step into and determine why something is not failing. For example, the test shown above helped me to trace down a problem with operator precedence and function evaluation. And these are very basic tests, as well.

I’m also working on Unit Test related features and capabilities, which includes integration into Jenkins, but for obvious reasons I can’t be going and showing you that, now can I? 😉

Have something to say about this post? Comment!