Welcome to Habanero Land!   Register  |  Login
You are here:   Blogs
  So, why do you need to register to download Habanero and access the additional materials? 
The success of any open source project is based on the community built around it. So go ahead, register / login and get involved!
Blog Roll
 
Categories
 
Search Blog
 
 
Habanero Cloud
 
Habanero Archive
 
Recent Blog Posts
 
 
Mar 4

Written by: brettright
Thursday, March 04, 2010 1:39 PM  RssIcon

Learning to write good tests can be hard. There are a lot of things to learn technologies to master and if you have been programming for some time then there are some bad habits to undo.

I train a lot of people to do TDD and have learnt from this that there a few small tricks that will significantly help you write a good test.

This blog assumes that you are familiar with the Red, Green Refactor process of test driven development and have some exposure to a unit testing framework such as NUnit.

I also assume you are familiar with the concept that TDD is not a testing activity but is in fact a design and development activity.

In this blog I go through the parts of what I consider to be a good test.

I have taken the example test from some tests that were written for the new Firestarter.

[Test]
public void Test_CreateReverseRelationship_WhenSingle_ShouldSetAsMultiple()
{
    //---------------Set up test pack-------------------
   IDMRelationship relationship = GetMockRelationship();
   SetAsSingle(relationship);
   IDMClass relatedClass = GetMockClass();
   DMSolutionPostLoadProcessor processor = GetProcessorWithAutoMocks();
   //---------------Assert Precondition----------------
   Assert.IsTrue(relationship.IsSingle, "Should b single");
   //---------------Execute Test ----------------------
   var reverseRelationship = processor.CreateReverseRelationship(relatedClass, relationship);
   //---------------Test Result -----------------------
   Assert.AreEqual(Cardinality.Multiple, reverseRelationship.Cardinality);
 }

Let start with the Name - In my opinion the Name is the most important part of the test.

If you can correctly write the name then you have correctly defined the requirement.

I still prefix all my test methods with Test (This is a throw back to the old days before attributes and .Net when we used reflection and method names to find the test methods).

Next is the Method name that I am testing (This is unit testing so you should always be testing one and only one method (We will look at integration and acceptance testing in other blog posts.

I put the method next so that all my tests for a single Method are grouped together by the Test Runner and Visual Studio.

 

The next part of the name is effectively the precoditions I start this with When if there are multiple Preconditions I use And for the second and third precondition

e.g. WhenSingleAndNameNotSet. Not all tests will have a When but I find the vast majority do.

 

The last part of the test Represents the Expected result what should the method under test do.

I prefix this with Should I use should because I am writing the test before the behaviour. I am also seeing the test as a specification. Specifications change over time (especially if you are doing agile) and should has the phsychological impact of being a little more flexible than Must.

 

Once you have correctly named your test it is usually pretty easy to write the test body.

The Test Body is broken  into 4 parts.

1) Setup in this section you set the objects required to be tested up. It is critical that this is done first and seperated from all assert and clearly seperated from the Method Under Test (SUT). The reason for this is that it makes it easier to understand the details of the test in the months and years to come.\

2) Assert Preconditions - The objective of this section is to not only convey information i.e. that the Relationship is Single before the method is called. Our team has found the use of Preconditions incredibly usefull especially since they ensure that your Test Pack is set up correctly. This is particularly critical if you are a Classisict Tester and not a Mockist. The reason is that over time especially in big systems some behaviour may change or some bug may have been introduces. You may get a number of failing tests as a result of this. If you have good Precodition Asserts you do not need to figure out which test is actually failing because its SUT (Method under test) has changed. All you have to do is find the test whose Test Results is failing fix this and the tests that are dependent upon this as setup data should be fixed.

3) Execute the Method Under test.

4) Test Result: Assert that the Method has executed correctly as per your Test Should.

 

I hope you find this usefull. I have found that not only does it give our team a template to help us define our tests but looking at the tests for a class give the reader a pretty good idea of what the class is supposed to do. When tests fails we can generally determine the cause of failure by just looking at the names of the tests that are failing.

 

Below is the Resharper Template that we use for quickly creating the test method layout.

        [Test]
        public void Test_$Method$()
        {
            //---------------Set up test pack-------------------
            $END$
            //---------------Assert Precondition----------------
            
            //---------------Execute Test ----------------------
           
            //---------------Test Result -----------------------
            Assert.Fail("Not Yet Implemented");
        }

Attached is a set of Resharper Templates that we use for testing to make it easier to write tests quickly and a Code Snippet for the test nethod above (for those who do not have Resharper) this code snippet needs to be placed in the <Documents>\Visual Studio 2008\Code Snippets\Visual C#\My Code Snippets folder.

TestCodeSnippet.zip

ResharperTemplates.zip


Your name:
Gravatar Preview
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Add Comment   Cancel 

Get Habanero at SourceForge.net. Fast, secure and Free Open Source software downloads