NUnit Technical Whitepaper

Assertions
Assertions are central to unit testing in any of the xUnit frameworks, and NUnit is no exception. NUnit provides a rich set of assertions as static methods of the Assert class.

If an assertion fails, the method call does not return and an error is reported. If a test contains multiple assertions, any that follow the one that failed will not be executed. For this reason, it's usually best to try for one assertion per test.

Each method may be called without a message, with a simple text message or with a message and arguments. In the last case the message is formatted using the provided text and arguments.

For convenience of presentation, we list the available assertions in three groups:
comparisons, single condition tests and utility methods.

Comparisons
Assertions that perform comparisons are often your best choice because they report both expected and actual values. The expected value is always the first argument. NUnit provides the following comparison asserts:

Assert.AreEqual( int expected, int actual );
Assert.AreEqual( int expected, int actual, string message );
Assert.AreEqual( int expected, int actual, string message, object[] parms );
Assert.AreEqual( decimal expected, decimal actual );
Assert.AreEqual( decimal expected, decimal actual, string message );
Assert.AreEqual( decimal expected, decimal actual, string message, object[] parms );
Assert.AreEqual( float expected, float actual, float tolerance );
Assert.AreEqual( float expected, float actual, float tolerance, string message );
Assert.AreEqual( float expected, float actual, float tolerance, string message, object[] parms );
Assert.AreEqual( double expected, double actual, double tolerance );
Assert.AreEqual( double expected, double actual, double tolerance, string message );
Assert.AreEqual( double expected, double actual, double tolerance, string message, object[] parms );
Assert.AreEqual( object expected, object actual );
Assert.AreEqual( object expected, object actual, string message );
Assert.AreEqual( object expected, object actual, string message, object[] parms );
Assert.AreSame( object expected, object actual );
Assert.AreSame( object expected, object actual, string message );
Assert.AreSame( object expected, object actual, string message, object[] parms );

The AreSame method tests that the same objects are referenced by both arguments. All the variants of AreEqual test for equality.

Overloaded AreEqual methods are provided for the most common types. In addition, the overload that compares two objects makes special provisions so that numeric values of different types compare as expected. This makes it possible for asserts like the following to succeed:

 Assert.AreEqual( 5, 5.0 )

Starting with version 2.2, special provision is also made for comparing arrays. Two arrays will be treated as equal by Assert.AreEqual if they are the same length and each of the corresponding elements is equal. Note: In version 2.2, this only applies to arrays, not to other collection types, such as ArrayList.

Condition Tests
Methods that test a specific condition are named for the condition they test and take the value tested as their first argument and, optionally a message as the second. The following methods are provided:

Assert.IsTrue( bool condition );
Assert.IsTrue( bool condition, string message );
Assert.IsTrue( bool condition, string message, object[] parms );
Assert.IsFalse( bool condition);
Assert.IsFalse( bool condition, string message );
Assert.IsFalse( bool condition, string message, object[] parms );
Assert.IsNull( object anObject );
Assert.IsNull( object anObject, string message );
Assert.IsNull( object anObject, string message, object[] parms );
Assert.IsNotNull( object anObject );
Assert.IsNotNull( object anObject, string message );
Assert.IsNotNull( object anObject, string message, object[] parms );

Utility Methods
Two utility methods, Fail() and Ignore() are provided in order to allow more direct control of the test process:

Assert.Fail();
Assert.Fail( string message );
Assert.Fail( string message, object[] parms );
Assert.Ignore(); Assert.Ignore( string message );
Assert.Ignore( string message, object[] parms );

The Assert.Fail method provides you with the ability to generate a failure based on tests that are not encapsulated by the other methods. It is also useful in developing your own project-specific assertions.

Here's an example of its use to create a private assertion that tests whether a string contains an expected value.

public void AssertStringContains( string expected, string actual ) 

    AssertStringContains( expected, text, 
string.Empty ); 
}
 
public void AssertStringContains( string expected, string actual, string message ) 

    
if ( actual.IsIndexOf( expected ) < 0 ) 
        Assert.Fail( 
string message ); 
}

The Assert.Ignore method provides you with the ability to dynamically cause a test or suite to be ignored at runtime. It may be called in a test, setup or fixture setup method. We recommend that you use this only in isolated cases. The category facility is provided for more extensive inclusion or exclusion of tests or you may elect to simply divide tests run on different occasions into different assemblies.

Attributes
Version 1 of NUnit used the classic approach to identifying tests based on inheritance and naming conventions. From version 2.0 on, NUnit has used custom attributes for this purpose.

Because NUnit test fixtures do not inherit from a framework class, the developer is free to use inheritance in other ways. And because there is no arbitrary convention for naming tests, the choice of names can be entirely oriented toward communicating the purpose of the test.

All NUnit attributes are contained in the NUnit.Framework namespace. Each source file that contains tests must include a using statement for that namespace and the project must reference the framework assembly, nunit.framework.dll.

Test Fixture (NUnit 2.0)
This is the attribute that marks a class that contains tests and, optionally, setup or teardown methods.

There are a few restrictions on a class that is used as a test fixture.

It must be a publicly exported type or NUnit will not see it.
It must have a default constructor or NUnit will not be able to construct it.
The constructor should not have any side effects, since NUnit may construct the class multiple times in the course of a session.

Example:

namespace NUnit.Tests 

    
using System; using NUnit.Framework; 
    [TestFixture] 
    
public class SuccessTests 
    

        
//  
    }
 
}

Test (NUnit 2.0)
The Test attribute marks a specific method inside a class that has already been marked as a TestFixture, as a test method. For backwards compatibility with previous versions of Nunit a test method will also be found if the first 4 letters are "test" regardless of case.

The signature for a test method is defined as follows:

 public void MethodName()

Note that there must be no parameters. If the programmer marks a test method that does not have the correct signature it will not be run and it will appear in the Test Not Run area in the UI that ran the program.

Example:

namespace NUnit.Tests 

    
using System; using NUnit.Framework; 
    [TestFixture] 
public class SuccessTests 
    

        [Test] 
        
public void Add()/*  */ } 
        
public void TestSubtract() /* backwards compatibility */ } 
    }
 
}


These attributes are used to construct the test environment prior to running the tests
(TestFixtureSetUp and SetUp) and also to restore the environment after the tests are completed (TestFixtureTearDown and TearDown)

TestFixtureSetUp/TestFixtureTearDown (NUnit 2.1)
These two attributes are used inside a TestFixture to provide a single set of functions that are performed once (TestFixtureSetUp) prior to executing any of the tests in the fixture and once after (TestFixtureTearDown) all tests are completed. A TestFixture can have only one TestFixtureSetUp method and only one TestFixtureTearDown method. If more than one of each type is defined the TestFixture will not be run. It will compile however.

Example:

namespace NUnit.Tests 

    
using System; 
    
using NUnit.Framework; 
    [TestFixture] 
    
public class SuccessTests 
    

        [TestFixtureSetUp] 
        
public void Init() /*  */ } 
        [TestFixtureTearDown] 
        
public void Dispose() /*  */ } 
        [Test] 
public void Add() /*  */ } 
    }
 
}


SetUp/TearDown (NUnit 2.0)
These two attributes are used inside a TestFixture to provide a common set of functions that are performed prior (SetUp) and after (TearDown) a test method is called. A TestFixture can have only one SetUp method and only one TearDown method. If more than one of each type is defined the TestFixture will not be run. It will compile however.

Example:

namespace NUnit.Tests 

    
using System; 
    
using NUnit.Framework; 
    [TestFixture] 
    
public class SuccessTests 
    

        [SetUp] 
        
public void Init() /*  */ } 
        [TearDown] 
public void Dispose() /* */ } 
        [Test] 
public void Add() /*  */ } 
    }
 
}

SetUp/TearDown Inheritance
These two attributes are inherited from base classes. Therefore, if a base class has defined a SetUp method that method will be called prior to execution of test methods in the derived class. If you wish to add more SetUp/TearDown functionality in a derived class you need to mark the method with the appropriate attribute and then call the base classes method.


Expected Exception (NUnit 2.0)
This is the way to specify that the execution of a test will throw an exception. This attribute takes a parameter which is a Type. The runner will execute the test and if it throws the specific exception, then the test passes. If it throws a different exception the test will fail. This is true even if the thrown exception inherits from the expected exception.

Example:

namespace NUnit.Tests 

    
using System; 
    
using NUnit.Framework; 
    [TestFixture] 
public class SuccessTests 
    

        [Test] 
        [ExpectedException(
typeof(InvalidOperationException))] 
        
public void ExpectAnException() /*  */ } 
    }
 
}


Category (NUnit 2.2)
The Category attribute provides an alternative to suites for dealing with groups of tests. Either individual test cases or fixtures may be identified as belonging to a particular category. Both the gui and console test runners allow specifying a list of categories to be included in or excluded from the run. When categories are used, only the tests in the selected categories will be run. Those tests in categories that are not selected are not reported at all.

This feature is accessible by use of the /include and /exclude arguments to the console runner and through a separate "Categories" tab in the gui. The gui provides a visual indication of which categories are selected at any time.

Test Fixture Syntax

namespace NUnit.Tests 

    
using System; 
    
using NUnit.Framework; 
    [TestFixture]
    [Category(
"LongRunning")] 
    
public class LongRunningTests 
         { //  }
}

Test Syntax
namespace NUnit.Tests 

    
using System; 
    
using NUnit.Framework; 
    [TestFixture] 
    
public class SuccessTests
    

        [Test] 
        [Category(
"Long")] 
        
public void VeryLongTest() 
        
/*  */ } 
    }

}


Explicit (NUnit 2.2)
The Explicit attribute causes a test or test fixture to be ignored unless it is explicitly
selected for running. The test or fixture will be run if it is selected in the gui, if its name
is specified on the console runner command line as the fixture to run or if it is included by use of a Category filter.

If a test or fixture with the Explicit attribute is encountered in the course of running tests, the runner treats it as if it had been ignored. The progress bar turns yellow and the test is listed in the report of tests not run.

Test Fixture Syntax

namespace NUnit.Tests 

    
using System; 
    
using NUnit.Framework; 
    [TestFixture, Explicit] 
    
public class ExplicitTests //  } 
}

Test Syntax

namespace NUnit.Tests 

    
using System; 
    
using NUnit.Framework; 
    [TestFixture] 
    
public class SuccessTests 
    

        [Test, Explicit] 
        
public void ExplicitTest() /*  */ } 
    }

}


Suite (NUnit 2.0)
The Suite Attribute is used to define subsets of suites based on user preference. The belief by the developers of this version is that the need for this will diminish because of the dynamic creation mechanism provided by the framework. However it is provided for backwards compatibility.

Note: There is no way to run user-defined suites in the forms interface.

Suite Attribute syntax

namespace NUnit.Tests 

    
using System; 
    
using NUnit.Framework; 
    
public class AllTests 
    

        [Suite]
        
public static TestSuite Suite 
        

            
get 
            

                TestSuite suite 
= new TestSuite("All Tests"); 
                suite.Add(
new OneTestCase()); 
                suite.Add(
new Assemblies.AssemblyTests()); 
                suite.Add(
new AssertionTest()); 
                
return suite; 
            }
 
        }
 
    }
 
}


Ignore (NUnit 2.0)
The ignore attribute is an attribute to not run a test or test fixture for a period of time. The person marks either a Test or a TestFixture with the Ignore Attribute. The running program sees the attribute and does not run the test or tests. The progress bar will turn yellow if a test is not run and the test will be mentioned in the reports that it was not run.

This feature should be used to temporarily not run a test or fixture. This is a better mechanism than commenting out the test or renaming methods, since the tests will be compiled with the rest of the code and there is an indication at run time that a test is not being run. This insures that tests will not be forgotten.

Test Fixture Syntax

namespace NUnit.Tests 

    
using System; 
    
using NUnit.Framework; 
    [TestFixture] 
    [Ignore(
"Ignore a fixture")] 
    
public class SuccessTests //  } 
}

Test Syntax

namespace NUnit.Tests 

    
using System; 
    
using NUnit.Framework; 
    [TestFixture] 
    
public class SuccessTests 
    

        [Test] 
        [Ignore(
"Ignore a test")] 
        
public void IgnoredTest() /*  */ } 
    }

}

[Finished]

posted @ 2004-12-11 14:58  张逸  阅读(1168)  评论(0编辑  收藏  举报