Test-Driven Development in Microsoft .NET (Microsoft Professional)

Now that you have successfully coded, compiled, and executed your first programmer tests, let s spend some time exploring the vocabulary of the NUnit Framework. So far, we have talked about test fixtures, test cases, and test runners.

In the following section, we discuss test case.

Test Case

Test case is a self-validating programmer test that can be automatically discovered and executed independently of other test cases by a test runner. Following are a few important points about test case:

Test Suite

A test suite is a collection of test cases or other test suites. The relationship between test cases and test suites is described by the Composite [2] pattern.

Test Fixture

A test fixture is a group of test cases sharing a common set of run-time resources.

Now that the concepts are defined, let s look at our test again:

using System; using NUnit.Framework; namespace NUnitQuickStart { [TestFixture] public class NumbersFixture { [Test] public void AddTwoNumbers() { int a = 1; int b = 2; int sum = a + b; Assert.AreEqual(3, sum); } } }

The second line ( using NUnit.Framework; ) references the NUnit namespace, which contains all the classes you need to use to write your programmer tests. Classes populating this namespace are packaged in nunit.framework.dll .

Tests and Test Fixtures

One of the features of the NUnit Framework is its use of custom attributes. Attributes in .NET are the standard mechanisms to extend metadata about run- time entities. In this case, the run-time entities of interest are as follows :

As the previous example demonstrates , the [TestFixture] attribute can be used to mark a class as a test class. The test class has to be public to be discovered by the test runner. The [Test] attribute is used to mark a method as a test method. A test method must follow these rules:

Working with Test Runners

A test runner is a program that can be used to automatically discover, organize, run, and collect the results of execution of programmer tests. Until now, we have been working with NUnit-Gui test runner. One of the features of this test runner is its capability to represent the composite structure of the test assembly using a tree control, which provides a good visualization of the structure of the tests in the assembly. The test runner performs an automatic discovery of the tests in the assembly by following this simple two-step process:

  1. Find all classes marked with the [TestFixture] attribute in the assembly.

  2. For each fixture found, create a test suite and populate this test suite with all the test methods discovered in the test fixture.

After the test suite for the assembly is built, the test runner renders a visual representation of the test suite. In this tree, each non-leaf node maps to a test suite, and each leaf node maps to a test case. When the assembly is loaded, the tests can be run. You can run the entire suite or you might choose to run an individual node in the tree (a test suite or a test case) and run only that node and all its descendants. The test runner collects the results of the execution of each test case it runs and presents these results to you.

Assertions

A test case must be self-verifying. To write a self-verifying test case, we need a mechanism that supports such a verification process. In NUnit, the mechanism is called an assertion , which is a simple statement of truth (or what the programmer believes to be the truth). Here are some examples of assertions:

Assertions can be rather arbitrary and might lack mechanisms to support their verification. In NUnit, we decided to support the mechanisms to verify the first type of assertions.

In the example we wrote, we used the mechanism of assertions to verify the results of adding two numbers . Let s make a little change to this example. The only statement we will change is the following:

Assert.AreEqual( 4 ,sum);

Obviously, this assumption will fail. To indicate failure, the progress bar turns red, and the tree nodes turn red to indicate which test failed. Note that the test tree represents a failure ”the parent nodes are colored red if at least one child note is red (sibling nodes of a failing node are not affected by its failure). Figure A-5 demonstrates the NUnit-Gui window after we rerun the test:

Figure A-5: Assertion failure in the NUnit-Gui test runner

This simple example demonstrates the role that assertions play in NUnit Framework. This role is twofold:

Let s move on to a few more examples to demonstrate some other capabilities of NUnit.

[1] This requirement is an adaptation of the idea of referential transparency , which is borrowed from functional programming languages. A purely applicative program is completely devoid of any side effects, so it is much more conducive to mathematical verification of the program s correctness.

[2] See Design Patterns.

Категории