BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Testing
.NET 1.1+

Unit Testing

This is the first in a series of articles describing the use of automated unit testing techniques. Unit testing allows verification of the functionality of a program. Automated unit testing validates software automatically by executing test code.

What is Unit Testing?

Unit testing is the process of validating the correctness of a small section of code. The target code may be a method within a class, a group of members or even entire components that are isolated from all or most of their dependencies. Unit testing is generally performed by programmers, rather than testing personnel, as it requires knowledge of the structure of the code in additional to understanding the overall functionality of a program. For example, a set of unit tests may be used to verify that a complex algorithm is operating correctly. This could be too time-consuming to identify during system testing.

Unit testing is only one link in the chain of testing procedures required for the successful release of professional software. Other testing processes, such as integration testing, system testing, acceptance testing, performance testing and usability testing are also essential. These testing procedures tend to involve more manual work than unit testing, which may be substantially automated. However, it is possible to introduce some automation in other areas.

What is an Automated Unit Test?

An automated unit test is a piece of code that exercises project code to verify that it functions correctly. The test code is usually held in a separate project that contains a suite of tests for the target software. Automated testing code may be entirely generated by the developer and compiled into an executable program. However, it is more common to use a testing framework that standardises the structure of the tests and a test runner that executes the tests and provides feedback in a logical manner.

Manual unit testing is laborious and usually tedious, leading to mistakes or reduced testing being carried out. Automating unit testing allows entire suites containing hundreds, thousands or even hundreds or thousands of tests to be executed quickly and repeatedly. It assists greatly with regression testing, as each time a change to the software is made, all previous unit tests can be executed, ensuring that no new bugs have been introduced.

Other Benefits of Automated Unit Testing

The primary benefit of unit testing is the increased confidence that your code is behaving correctly. Some other benefits are described by many programmers. A key benefit that is conveyed by practitioners of test-driven development (TDD), also known as test-driven design, is that unit tests can improve the design of your software. Unit testing requires that small sections of code are validated independently. As we shall see later in the tutorial, tests should seek to isolate the class or method under test from its dependencies. In order to achieve testable code, it is common to follow the SOLID principles. However, it is quite possible to have successful tests and still have a poor quality design.

Another benefit of having a full suite of unit tests is that refactoring can become easier. Where refactoring to improve the quality of the design or reduce code duplication, the functionality of the software is generally unchanged. In such cases, the unit tests can remain unchanged too. The test suite can therefore be executed as a regression test after each stage of refactoring. If a new bug is introduced, the tests may identify it early and allow it to be fixed before it is compounded by the addition of new functionality.

Test suites can enhance the documentation for a project. Often the only documentation for a programmer is a set of comments in the code. If those comments are not maintained when the code changes, they can become incorrect, causing more problems than if they were not present. Unit tests always provide current examples of how the target software is used. However, unit tests should not be considered a full replacement for all documentation, only as an enhancement to other items.

Limitations

There are some things that are difficult or time-consuming to unit test. One example is the user interface of your software. There are design patterns that minimise the amount of functionality in the user interface (UI) layer, allowing the code to exist separately from the graphical elements and making that code testable. This leaves a very thin layer of UI components that require an alternative testing approach. Although there are some automated UI testing tools available they do have limitations. This will undoubtedly improve over time.

Common Misconceptions

There are many arguments presented against automated unit testing. To complete the first instalment of this tutorial I will describe some of the more common objections.

Writing Tests Takes Too Long

Possibly the most common objection to writing unit tests is that the process of creating the tests takes too long. It is certainly true that writing test code takes time. Sometimes it will take you longer to write the tests than to create the code that you are validating. However, testing has to happen at some point in the project. If you do not create unit tests as you write your code, the testing must happen later in the project, be it automated or manual testing or, in the worst case, testing performed by the end users. Generally, bugs found later in the development process, or during the maintenance phase of a project, are more time-consuming to rectify. Although avoiding writing unit tests may save time early in the process, it is likely that this saving will be outweighed by the additional effort required to debug your software later.

There are some elements of code that are difficult to test, perhaps because of limitations in testing tools. For example, there are problems with testing code that has static dependencies. In many cases there are tricks that will allow you to test these elements. In other cases you may consciously decide not to include these elements in your automated test suite, instead testing manually. There are also some parts of your code that are so simplistic that they do not require testing. For example, it is usually not worthwhile testing properties that merely provide getters and setters for an underlying backing store variable. Tests for these properties would be tests that C# works correctly; something that only Microsoft should be testing and that there is little you could do to fix if a problem was found.

9 March 2011