Saturday, November 17, 2007

The practice of coding against interfaces is already a well recognised best practice for software development, one of the advantages of this is that it helps loosen the dependencies between a class and the various other classes it uses. An application where this can be extremely useful is when unit testing your code, by loosening the dependencies of a class it becomes possible to test a class in isolation.

A good example of how to use these would be in data access classes, the real data access class would undoubtedly make calls to a physical database which would required configuration etc. However when testing a class that depends on the data access class we don’t want this dependency. Therefore the solution is simple. Define an interface, make both he real and mock classes implement this interface, the only difference is that the real implementation would go ahead and make calls to insert, update and delete from a database the mock will return only hard coded values so that you know exactly what to expect when testing a class that uses the data access components.

There are various frameworks that help to facilitate the creation of mock objects such as NMock, these are slightly more complex and give some extra features but the principle of coding to interfaces must be adhered to in order to take advantage of such frameworks.

To see an example of using mock objects see my post on PrivateObject, here I have simply used standard interfaces as this proved effective enough to conduct the testing. If your situation requires something more you can always look into NMock which is a free download.

posted on Saturday, November 17, 2007 2:53:25 PM (GMT Standard Time, UTC+00:00)  #    Add Comment | Comments [1]
 Thursday, November 15, 2007

PrivateObject have been included in Visual Studio 2005 team edition but since the release of Visual Studio 2008 they have been included in the professional edition, making them available for a wider number of developers.

So what’s the fuss all about? Simply as I’ve stated in earlier posts a PrivateObject allows you to access private members of an object. This can be extremely useful when unit testing an application as combined with mock objects these can create the mechanism that allows tests to be conducted in isolation.

For example, take a look at the class diagram below. In this scenario the person class provides the method CalculatePay this will return the amount of pay an employee should receive. To do this the Person class will make a call to the GetHours() method of a persons TimeSheet. The time sheet is declared as a private variable and is therefore inaccessible to anything outside of the Person class.


So how do we test the CalculatePay method? The TimeSheet class will possibly make calls to a database or an enterprise system that holds this data therefore introducing many possible points of failure, so simply testing all at once won’t give us the full benefit of unit testing, it might tell us something has gone wrong but it can’t tell us what or where, and we all love error message that tell us something has gone wrong contact your administrator, personally I hate this type of error, if something has gone wrong I’d like to know what it is exactly as this can save significant time when fixing the problem. The way we get the specific details of what has gone wrong is isolating the tests, only by isolating the tests and completely controlling the situation can we accurately predict what a method should do, and the way I go about this is using Mock objects and the PrivateObject class.

For more details on Mock Objects see my post on the topic.


In this solution I will make the TimeSheet class implement an interface that defines the GetHours method. I will then create a new class called MockTimeSheet that implements the same interface. However the MockTimeSheet class will return a hard coded value for the hours work, this is important as a hard coded value allows me to know exactly what to expect when I call the method. After defining the mock object I will use the PrivateObject to update the private fields of the Person class before running the test.


The class diagram below gives an overview of  what the solution will now look like.




We’ll start to implement this example and as always we’ll start by implementing the unit tests first.

  1. Open Visual Studio 2008 and create a new blank solution called “PrivateObjectExample”.
  2. Add a new test project called PayrollTests
  3. Add a new class library project with a single empty public class called Person. The solution should now have the following items.




  4. Rick click on the PayrollTests project and select Add -> Unit Test






  5. Tick the tick box beside the Payroll project icon and click ok.






  6. We now want to call the CalculatePay method in a controlled manner so that we know exactly what to expect and therefore what to test against. To do this we will need to set the hourly rate and control the number of hours that the TimeSheet class returns. This is where mock objects come into play. Add a new interface to the Payroll project called ITimeSheet which has one method GetHours. The code snippet below shows what the interface should look like.

    namespace Payroll
    {
    interface ITimeSheet
    {
    double GetHours();
    }
    }

  7. We will now create a mock object that implements the ITimeSheet interface. Because the mock object is specific to testing it is therefore added to the PayrollTests projects. Right click on the PayrollTests project and select add new class. Call the class MockTimeSheet and implement the ITimeSheet interface the code below shows what you should have.

    using Payroll;

    namespace PayrolTests
    {
    public class MockTimeSheet: ITimeSheet
    {
    public double GetHours()
    {
    return 38;
    }

    }
    }

  8. We can now start to define the test. To start with we create an instance of the Person class and set the HourlyRate property to £5 per hour. At this point we now need to set the class to use the mock time sheet. This is done by creating an instance of the PrivateObject class and calling the SetField method. The set field method takes two parameters, a string which is the name of the variable you wish to set and the second parameter is the value you wish to assign to the private field. After the private field has been set it is simply a matter of calling the CalculatePay method of Person class and using the Assert class to test that the calculated pay matches what is expected. The code snippet below shows the code for the test method. Just for interest note the call to the Assert.AreEqual takes three parameters, this third parameter is a message that is displayed when the test fails.

    [TestMethod()]
    public void CalculatePayTest()
    {
    Person person = new Person();
    person.HourlyRate = 10.00;

    PrivateObject po = new PrivateObject(person);
    po.SetField("_timeSheet", new MockTimeSheet());

    double pay = person.CalculatePay();

    Assert.AreEqual(38, pay, "Calculated pay does not match the expected pay!");
    }

  9. You can download the complete solution here.
    PrivateObjectExample.zip (60.25 KB)
posted on Thursday, November 15, 2007 11:13:34 PM (GMT Standard Time, UTC+00:00)  #    Add Comment | Comments [0]
 Wednesday, November 14, 2007

Introduction
In my last post I gave a very brief introduction to the Test-Driven Development (TDD) process and demonstrated a very simple project in Visual Studio 2008 that showed how to create tests for a class. In this post I will introduce more of the tools and classes available in Visual Studio 2008.

In this post I will look at:

  • The TestContext class.
  • The Attributes available for defining test classes and methods.
  • The Assert class.
  • Private objects
  • Debugging tests within Visual Studio 2008.

The TestContext class
The TestContext class allows you to get a handle on the context in which the test is being executed. From this you can obtain useful information. For example when testing an ASP.NET application the TestContext class allows you to get a handle to the Page class. From this you will then be able to get a handle to the various controls contained on the page, this is an example I will expand upon in future posts.

 When you use the wizards built into Visual Studio 2008 to generate your unit test classes a TestContext property and corresponding member variable will be automatically added to your class. The runtime will take care of setting this property for you, therefore freeing you to simply use the TestContext as you need. The code snippet below shows the definition of the TestContext property and the corresponding member variable, this is not code you will have to write unless you are writing your test manually.

        private TestContext testContextInstance;

/// <summary> ///Gets or sets the test context which provides ///information about and functionality for the current test run. ///</summary> public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}

Attributes for Testing
All classes related to unit testing is Visual Studio 2008 are located in the namespace Microsoft.VisualStudio.TestTools.UnitTesting. I’ve already introduced two attributes in my last post the TestClass and the TestMethod attributes, these are the most common attributes that you will need for every test you write, the list below illustrates some of the other attributes that you may find useful when writing tests.

AssemblyInitialize and AssemblyCleanup
Allows you to identify methods that should be called before any tests in an assembly are executed and after all tests have completed.
 

ClassInitialize and ClassCleanup
Similar to the AssemblyInitialize and AssemblyCleanup except these are used to identify methods that are called before and after all tests in a test class are executed.

TestInitialize and TestCleanup
Again similar to AssemblyInitialize, AssemblyCleanup, ClassInitialize and ClassCleanup these attributes allow you to define methods that should be called before and after each individual test is executed.

Description
This attribute allows you to include a descriptive string that can then be listed in the test results window. The code snippet illustrates applying this attribute to the TestAddPositiveNumbers methods from my previous post and the screen shot shows how the description is displayed in the test results window. This can be a useful addition to helping convey the reasons for having a test but personally I would recommend striving to create meaningful names for your tests methods, avoid using names like ‘Test1’ for your test methods.

        [TestMethod]
[Description("Try and add two positive Numbers (2+2) and ensure that the answer is 4")]
public void TestAddPositiveNumbers()
{
Calculator cal = new Calculator();
int result = cal.Add(2, 2);
Assert.AreEqual(4, result);
}



Note: By default the description column is not displayed in the test results window, to display this column right click on the test results window and select “Add/Remove Columns…” this will display the following dialog that allows you to select the columns you wish to display.

 




ExpectedException
A very useful attribute this allows you to tell the runtime to expect a particular exception when running a test. When conducting unit tests you should be testing both normal and erroneous conditions, so you should pass invalid data to your methods and use unit tests to verify that your method can handle the error conditions appropriately. This is where the ExpectedException attribute can be useful. Normally if an exception occurs while executing a tests this will cause the test to fail, however telling the runtime to expect the exception will allow the test to pass, provided the exception raised match the type expected.


To illustrate this I have added a divide method to the calculator class from my last post. One of the tests and the implementation of the divide method are shown below.

HostType
This attribute identifies the test as being run outside of the current environment. For example specifying the string “ASP.NET” as the parameter to this attribute allows you to run tests in the ASP.NET development server. This is an attribute I will explore in more depth with later posts when I’ll be looking at testing an ASP.NET application.

For more information on the attributes available and their usage see the MSDN documentation.

The Asset Class
Central to helping you construct unit tests the Assert class provides a set of static methods that evaluate a Boolean condition. If the condition evaluates to true then the assert passes otherwise the assert fails and the unit test will be listed as a fail in the test results window. This is a list of some of the methods the Assert class provides, for more details on these check out the MSDN documentation. At this stage I’m only listing them to make you aware of their existence, in later posts I will use these as I need to illustrate points.

  • AreEqual
  • AreNotEqual
  • AreNotSame
  • AreSame
  • Fail
  • IsFalse
  • IsInstanceOfType
  • IsNotInstanceOfType
  • IsNotNull
  • IsNull
  • IsTrue

Private objects
In the past when I’ve been writing unit test I have been trying to test a class which relies on another class which has an instance of this class as a private field, and in keeping with the ethos of unit testing by testing each class in isolation this has presented me with a dilemma, do I test the two in conjunction, or do I expose some means of allowing the field to be set. Neither of these has ever proved to be an ideal solution, testing in conjunction is a big no and writing extra code to make a field publicly available doesn’t sit well, if there was no need for the outside world to know of this field before then it should be private. With private objects you now have the ability to solve both of these problems. My next post will give an example of using private objects.

 Debugging tests in Visual Studio 2008
Debugging unit tests with Visual Studio 2008 is straight forward simply follow these steps: 

1.  Open your solution that contains the test projects

2.   Open the class that contains the test you wish to debug and add a breakpoint to that test.

3.    Select Test -> Debug -> All Tests in Solution. The keyboard short cut to debug all tests is Ctrl+R Ctrl+D

 An alternative to debugging all tests in the solution is to use the test results window to select the tests you wish to debug. Then click on the drop down menu on the Debug button on the test results window toolbar and select “Debug Checked Tests”.


Conclusion
In my previous post I identified the TDD process and in this post I have built on this to introduce many of the features available in Visual Studio 2008 to facilitate unit testing. In subsequent posts I will get more practical with code examples that show how to use these features. The first of these will introduce the use of private objects with some example code.

posted on Wednesday, November 14, 2007 8:51:52 PM (GMT Standard Time, UTC+00:00)  #    Add Comment | Comments [0]
 Saturday, November 10, 2007

Introduction
Test Drive Development (TDD) or unit testing are terms you may or may not have come across in the past, in this series of posts I’m going to look at TDD, I’ll give a brief overview and my arguments for TDD. In later posts I will begin to look more closely at the features available in Visual Studio 2008 to help you integrate TDD into your development process.

To start with lets look at the sport of rock climbing. As a climber climbs a route they will place ‘protection’ along the route. These are clipped onto the rope and rock face so that in the event  of a fall the ‘system’ catches the climber and all that is sustained is a bruised ego.  In contrast others will climb without any safety placed along the route, in the event of a fall in this scenario the outcome can be deadly.

The same is true for software development, TDD is your safety net, as your code evolves and new features are added or existing features extended you can move forward with confidence that your existing functionality has remained intact provided all the tests pass.  Be honest how many times have you been given the task of fixing a bug only to find the fix you have put in place has resulted in breaking another feature in the system? With TDD this situation can be avoided.

Some will make the argument that TDD means more effort and that makes it unfeasible in a commercial software development project. True there is a little more effort in writing the test code up front, however this is a one off, as the test code once completed should never have to change unless a business requirement changes. and having the tests in place creates a safety net that allows you to move forward with even more confidence, resulting in less time fixing features that have been broken by accident, therefore some of the investment in writing the tests can be reclaimed.

To successfully use TDD classes must be designed to do one thing and one thing only thus allowing them to be tested in complete isolation allowing you to pinpoint the location of bugs in your code. I’ve heard some tell me how this is impossible as this class relies on that classes and often a database is included in the mix. This is a fair point as systems are always comprised of multiple classes working together to accomplish the desired goal, but it should still be possible to isolate each class and test their functionality separately. A friend of mine once pointed out, if your classes are that tightly coupled that this is unachievable then your code isn’t written right. There’s a lot of truth to this statement and in these posts I’ll show some examples of how you can use simple techniques to isolate a class for testing.
 

The TDD Process
Essentially TDD is a very simple and straight forward process. You gather a set of requirements, for each requirement write one or more failing tests. After you have a set of failing tests you begin to write implementation code that will pass each of the tests. Once this code is completed and all the tests pass then you can be confident that the delivered code accurately meets the requirements.

You should avoid writing tests that do not have a corresponding requirement as this would lead to unnecessary implementation code being written. TDD should help you to focus on writing only the code that is required, and less code often means less bugs and less late nights.

It is possible to combine multiple classes together and test these, for example class A uses classes B and C. Here you could test class A and allow it to make the necessary calls to B and C if you want to achieve integration testing, however to get the true benefit of TDD you should at first test each of these classes in isolation as this will allow defects to be pinpointed to a specific class. All the examples that I use will focus to testing classes in isolation.


Getting Started With Visual Studio 2008
I am now going to introduce a simple example of creating a class library and a corresponding set of tests for the publicly exposed functionality. In this post I’m more concerned with introducing the techniques for creating and running unit tests than getting bogged down in a complex real world problem. In later posts I will introduce other more advanced features available in Visual Studio 2008 for TDD that will become more real world orientated such as testing an ASP.NET applications.


Show me the Code!!

For this example I’m keeping it very, very simple so that we focus on the techniques for writing a test and running it, this should take no more than fives minutes of your time to run through.

The scenario, you need to provide a class library that provides facilities to add, subtract and  multiply integer values. Told you it would be easy, so lets get started.

 1.     Start Visual Studio 2008

2.       Create a new blank solution called ‘MyFirstTDD’

3.     Add a new Test project call MathTests to the solution. Right click on the solution name in Solution Explorer and select “Add -> New Project …”. Delete UnitTest1.cs from the project.

4.   Add a new Class library to the solution called Math. Right click on the name of the solution in Solution Explorer and select “Add -> New Project …” Delete Class1.cs from the project.

5.   Now the test project will reference the classes in the actual class library, therefore you need to add a reference to the class library from the test project. To do this right click on the test project in Solution Explorer and select “Add Reference …”. Click the projects tab select Math and click ok.



6.   You now have the solution setup and we can being to write the code, test first of course.

7. Go to the test project, right click on the name and select Add -> New Test.. Name the test CalculatorTests.cs. This will generate a skeleton test class for the Calculator class that will be implemented later. For now pay attention to the TestClass and TestMethod attributes used at the class and method declarations respectively. The TestClass attribute signals that this class contains tests and the TestMethod attribute is used to define the individual tests. For methods marked with the TestMethod attribute to be considered valid tests they must be in a class that is marked with the TestClass attribute. For now remember when creating a test class you must mark it with the TestClass  attribute (Visual Studio will do this automatically when using the built in wizards to add your test class), also each method you wish to use as a test method must be marked with the TestMethod attrinbute.

8.     By default Visual Studio adds the method TestMethod1(), you can go ahead and delete this as we will be adding our own tests with more meaning full names.

9.     So now we start the actual development. Firstly we have to provide functionality to add, subtract and multiply integer values. This indicates that we should at the very least have three tests. So we will start by implementing a test that will validate that our Calculator class can add correctly.

10.  Open CalculatorTests.cs and add a new method called TestAddPositiveNumbers this method has a return type of void and takes no parameters, you should also mark this method with the TestMethod attribute.

   [TestMethod]
public void TestAddPositiveNumbers()
{
    Calculator cal = new Calculator();
    int result = cal.Add(2, 2);
    Assert.AreEqual(4, result);
}

11.  We will now implement the body of the test. To start with we will create an instance of out Calculator and call the Add method. We will get this test to ensure that two plus two always give us four. To do this we will use hard coded values, this is how you should code all your tests. Using hard coded values. It is important to use hard coded values as your tests must be conducted in a controlled environment where you know exactly what to expect from the methods you are testing.

12.  You can see from the code snippet that we simply create a new calculator and call the Add method passing two and two as parameters. Then we use the Assert class to check that the returned value matches four. The Assert class has a number of methods that can help with writing unit tests. Fort this post I’ll only be using the AreEquals method. This methods accepts two parameters and tests that they match, if they do not match then it will raise an exception and cause the test to fail, for now this is enough as I’ll look more closely at everything the Assert class provides in later posts.

13. Now we can try and compile the solution, which not surprisingly fails as we have not yet implemented our Calculator class. We will now define the calculator class but will only add enough code that allows the test class to compile and run, all tests should still fail.

14.  Right click on the Math project in solution explorer and select Add à Class ..

15.    Enter the name Calculator.cs and Add ok.

16.  Use the code snippet below to define the Add method for the Calculator. 

public int Add(int first, int second)
{
throw new NotImplementedException();
}

17.     The code should now compile.

18.    Having the code compile we can run the test at this point we expect the test to fail.

19.    To run the tests click Tests -> Run -> Run All Tests in Solution from the menu bar or use the keyboard shortcut Ctrl+R, A.

20. The tests will run and the test results window, shown below will indicate that your test has failed. At this time fails are good as we have not implemented any code, therefore if tests pass at this stage there would be little point in having them.


21.  Copy the code snippet below into CalculatorTests.cs compile and run the tests.

public void TestAddNegativeNumbers()
{
Calculator cal = new Calculator();
int result = cal.Add(-2, -2);
Assert.AreEqual(-4, result);
}

22.   Note that only one test has been run. This is because we have not added the TestMethod attribute to the TestAddNegativeNumbers method. Apply the attribute and run the tests again.

23.  We now have two failing tests.

24.  You should continue writing tests like this until all functionality has been tested. As this is only a simple blog we’ll skip out repeating these steps and implement the Add method and verify that both tests pass.

25.   Use the code snippet below to implement the add method.


public int Add(int first, int second)
{
    return first + second;
}

 26.     Compile the solution and run the test. In the test result window you can now see that the two tests have passed.

27.  This process of defining tests, verifying that they fail, implementing the code and verifying that the tests pass should continue until all the functionality has been implemented with supporting passing tests to verify it meets the requirements.


Conclusion
In this post I’ve defined the process for TDD and given a simple example of how to use TDD with Visual Studio 2008. In my next post I will look more closely at the nuts and bolts of the tools available in Visual Studio 2008 for implementing unit tests such as the various attributes and the methods available in the Assert class. 

If you would like to learn more about TDD I would recommend the book Test-Driven Development in Microsoft .NET by James W. Newkirk and Alexei A. Vorontsov. The examples in this book use NUnit but the techniques are applicable to Microsoft’s implementation of TDD.


Complete solution:
MyFirstTDD.zip (31.81 KB)
posted on Saturday, November 10, 2007 11:23:02 PM (GMT Standard Time, UTC+00:00)  #    Add Comment | Comments [0]