The Why of Unit Testing
The purpose of unit testing is to tear the larger pieces of an application into small isolated testable pieces of code. In doing so a developer can determine with greater accuracy the root cause of a defect in program logic.
Unit tests act as a canary in a mineshaft giving the developer an early warning of logic errors. A developer can be sure that while he writes Feature Z that Features X and Y weren’t broken in the process. And if they are a quick run of the unit tests will let the developer know.
What Makes Successful Tests
A unit test should be the following:
- Fast: A unit test should give a developer instant feedback that something is wrong
- Reliable: A unit test should give the same result regardless of where and when it is executed
- Accurate: A unit test should test the smallest piece of logic so errors can be pinpointed easily
- Flexible: A unit should account for normal and abnormal use cases
Getting Started in Visual Studio 2010
Visual Studio provides some methods to make creating unit tests easier. The easiest of which is to right-click on a method you want to test and click “Create Unit Tests…”, this will open the “Create Unit Tests” dialog.
From this dialog you can have Visual Studio stub out a basic unit test for the developer. The test won’t verify any actual logic and may contain errors.
At this point you can write as few or as many tests as required to test the logic in the target class. A real unit test for Debit() could look like the following:
To error is human, unit tests help the developer find their mistakes. With the unit testing project set as the startup project, debug the project. Visual Studio will present the “Test Results” dialog that will display the passing and failing tests.
Here the DebitTest() method has failed. Double-clicking the failed test will highlight the failing line of code in the test file. Right-clicking the test and selecting “View Test Result Details” will open a test result report with additional details.
Here we can see that actual balance after calling Debit() does not match the expected value.
MSTest provides three static classes that can be used to verify the results of the unit tests.
- Assert: This class contains methods to evaluate Boolean and equality, as well as methods to force failure and signify an inconclusive result.
- CollectionAssert: This class is designed to evaluate the contents of collections.
- StringAssert: The StringAssert class contains methods to evaluate strings, with methods such as Contains(), StartsWith(), and Matches().
All assert methods provide an overload that allows the developer to provide a more specific message to display in the event of a failure.