Saturday, October 19, 2013

TDD (Test Driven Development) .Net

In this post I am going to explain a little bit about the TDD, code coverage and feature coverage.

What is TDD? Simply Test Driven Development, what does it mean? It means that you are going to make your test cases first and then you are going to write minimum amount of code to pass all the test cases.

Not all the classes can be tested 100% because of some DB limitations or web service limitations or sometimes related to views or events but 50% of them that have limitation can be mocked and tested. Later on in my posts I will discuss about mocking but right now I am going to talk about a simple method 'Add' that takes two integer and returns an integer value. The code snippet will be in C# .

      public int Add(int a, int b) //prototype

What you expect from the signature what it should perform? Simply it will take two integer values and return the sum of them. e.g. 2 + 3 = 5. I am assuming the class name will be Maths.

Here's a Unit test of it.

   [TestClass]
   public class MathsTest
   {
         Maths obj;
      [TestInitialize]
      public void Setup()
      {
             obj = new Maths();
      }

      [TestCleanup]
      public void Cleanup()
      {
          //dispose any object or cleanup DB
      }

      [TestMethod]
      public void TestMethod1()
      {
         Assert.IsTrue(obj.Add(2, 3) == 5);
      }
   }

Now our test class is completed and now we can write a code for the Maths class. So here's the code snippet of Maths class with 'Add' function.

 public class Maths
   {
      public int Add(int a, int b)
      {
         return a + b;
      }
   }

Is it completed? We have tested this method so it should be but my answer is no, we have got a 100% coverage of the code but we have not tested it completely. So what are the missing functionalities and missing test cases. Following are the listed below.

1 - The arguments are not tested on the minimum values of integer.
2 - The arguments are not tested on the maximum values of integer.
3- The arguments are not tested on the negative values of integer.

Let's test the #2 test case. I expect if I am providing the max value of int type and it returns int type value then it should raise an exception.

      [TestMethod]
      [ExpectedException(typeof(OverflowException))]
      public void TestOverflowException()
      {
         int i = obj.Add(int.MaxValue, int.MaxValue);
      }

Run and test it, is it raising exception. No, why? Why it is not raising exception because there is a fault in a very simple code. Instead of writing the above one it should be like below. Just replace return line with this one.
         return checked(a + b);

Now run it, it is perfectly working as expected.

So you have seen how much the test cases are important. You can try yourself the other test cases as well.

There is one misconception if your class code is traversed 100% by your test class then it won't be a 100% test coverage until you have covered all the test cases as well. Hope this will help you in writing the code.

My next post will be about a design pattern of a unit test that you should follow.  

No comments:

Post a Comment