Thursday, February 16, 2012

TDD (Test-driven development) and Unit Test in Visual Studio 2010

    TDD is a software development method that you write the code uses your unit (usually it's a class or implementation of interface) first, this will cause the unit test failed. Then you write or change the unit code itself to make the unit test pass. TDD attracts more and more software developers' attention nowadays, so that Microsoft adds unit test feature in Visual Studio 2010. TDD is a big topic, there are many articles talking about it. I don't want to discuss too much in this blog. I would like to introduce how you do TDD with built-in unit test feature in Visual Studio 2010.

       Suppose your customer wants a class name Car and it must have a method named drive(). You decide to use TDD method to implement it. You add a unit test project into your solution in VS2010. The detail steps:

       1. Menu File->Add->New Project, select Test on the left pane, select Test Project on the right pane.

       2. Input the project name and click OK.

       3. A unit test project will be added to your solution. You can safely remove the auto-created UnitTest1.cs file from the unit test project because you will create your own later.

       After you create the unit test project, you add a CarTest class like following:

       [TestClass()]
       public class CarTest {

              [TestMethod]
              public void canDrive() {

                     Car car = new Car();

                     car.drive();

              }

       }

       Then you go to menu Test->Run->All Test in Solution to start the unit test, this will certainly fail. This failure is a "good" failure, because it drives you to write code to make the test pass. You add a class named Car, which has a method named drive(), into your application project.

       public class Car {

              public void drive() {

                     Console.WriteLine("drive car.")

              }

       }

       You run the unit test again. It is passed successfully this time. Next day, your customer tells you he wants to a new method name openSunRoof() to the Car. You add a canOpenSunRoof() into the CarTest class:

       [TestClass()]
       public class CarTest {

              [TestMethod]
              public void canDrive() {

                     Car car = new Car();

                     car.drive();

              }

              [TestMethod]
              public void canOpenSunRoof () {

                     Car car = new Car();

                     car.openSunRoof();

              }

       }

       Your application code fails to pass the unit test again. This drives you to add a new method named openSunRoof() to class Car:

       public class Car {

              public void drive() {

                     Console.WriteLine("drive car.")

              }

              public void openSunRoof () {

                     Console.WriteLine("open sun-roof.")

              }

       }

       Your code pass the unit test. Nice work!

       Above is just a very simple example to show how is TDD development circle like, it's not meaningful for such a small project. But in real world, keeping your project code unit test clean when you add new features to make it more and more complex is much more meaningful. And your colleagues will find your unit test classes are the best documents to show how to use your code.

       Maybe you are not comfortable with failures in unit test, you can write your code first and then add the unit test code later. VS 2010 also provides a function to make this happen: you can right-click the method you want to unit test and choose "Create Unit Test", you can see the method is pre-selected in the unit test creation dialog, click "OK" and VS 2010 will create a unit test class for you.

       Well, the downside of TDD is also obvious, it increases the code you need to write and maintain. Sometimes the unit test code itself also needs to be tested and  fixed. It's ironic, isn't it? But in the long run, it is worth.

No comments: