Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / DevOps / testing

Developing Factorial Application Using Test Driven Development

4.80/5 (9 votes)
28 Jan 2012CPOL4 min read 50.3K   315  
The aim of this article is developing a Factorial Application using Test Driven Development
TDD Cycle

Introduction

In this article, we have a look at Test Driven Development with an example. The example is Factorial calculator application. This simple application shows us how to develop an application by test driven development. I will write the "Test Driven Development" as "TDD" in article.

Background

When I first faced the Test Driven Development, I thought "it is unnecessary". But later, I read the articles about it and I show that TDD prevents the errors and problems before the delivered projects. It also creates reliable products, shows code coverages. These benefits were enough for me to begin TDD.

In this article, we will use the Visual Studio default Unit Test Framework. But if you don't want to use default framework, you have more choices in the market of Unit Tests.

Before You Start

Before writing your code, you should determine the requirements of the application. We will be developing a Factorial application in this article. So we should determine the Factorial requirements. Later, we can determine the test methods. If you want, you can directly begin writing tests and skip these steps. But making is worth it.

Requirements

  1. Factorial calculates the multiplication of the all positive numbers less than or equal Target Number(n).
  2. Target Number(n) is a non-negative integer.

Unit Tests

  1. Zero factorial is One 0! = 1
  2. One factorial is One 1! = 1*0! = 1
  3. Two factorial is Two 2! = 2*1! = 2
  4. Three factorial is Six 3! = 3*2! = 6

First step is creating a solution named FactorialApplication. And add a test project named FactorialCalculatorTests and a class library named FactorialCalculator in solution.

Solution

And now create a new class and write the first test method.

Test 1: Zero Factorial is One

C#
[TestMethod]
public void ZeroFactorialIsOne()
{
    Factorial calculator = new Factorial();
}

As you can see above, I created a calculator object that is of type Factorial but there is no class named Factorial. And you will get a lot of red squiggly lines under Factorial word.

Image 3

Let's create a class using options menu under the Factorial Word.

C#
[TestMethod]
public void ZeroFactorialIsOne()
{
    Factorial calculator = new Factorial();
    float result = calculator.GetFactorialOf(0);

    Assert.AreEqual(1, result);
} 

Yes, now I added a new result variable and assigned a calculator.GetFactorialOf(0) method result in it. But there is no method of Factorial in such. And I created a method in Factorial class.

Now we can have a look at the Factorial class.

C#
public class Factorial
{
    public float GetFactorialOf(int p)
    {
        throw new NotImplementedException();
    }
}

And now let's run the test method and see the result.

Test Failed

The test failed because we created method GetFactorialOf(int p) but did not implement it as seen above. Now we should do minimum intervention to pass the test.

C#
public class Factorial
{
    public float GetFactorialOf(int p)
    {
        return 1;
    }
}

The test method can pass now. Because assertion has verified.

Test Passed

Test 2: One Factorial is One

And now, we can create our second method. New assertion is "One Factorial is One". The new test method is as follows:

C#
[TestMethod]
public void OneFactorialIsOne()
{
    Factorial calculator = new Factorial();
    float result = calculator.GetFactorialOf(1);

    Assert.AreEqual(1, result);
}

This method has passed as well because GetFactorialOf(int p) method still supports our assertion.

Test 3: Two Factorial is Two

The third assertion is "Two factorial is Two".

C#
[TestMethod]
public void TwoFactorialIsTwo()
{
    Factorial calculator = new Factorial();
    float result = calculator.GetFactorialOf(2);

    Assert.AreEqual(2, result);
}

This method failed as follows:

Test Failed

Assert exception is shown, expected value is Two but method returned One. Now we should make minimum modification on GetFactorialOf(int p) method to pass the method. The modification shouldn't affect the other test results.

C#
public class Factorial
{
    public float GetFactorialOf(int p)
    {
        if (p < 2)
            return 1;

        return p;
    }
}

Test Passed

Test 4: Three Factorial is Six

C#
[TestMethod]
public void ThreeFactorialIsSix()
{
    Factorial calculator = new Factorial();
    float result = calculator.GetFactorialOf(3);

    Assert.AreEqual(6, result);
}    

But now this assertion failed.

Test Failed

New modification is required on GetFactorialOf(int p) method.

C#
public float GetFactorialOf(int p)
{
    if (p < 2)
        return 1;

    return p * GetFactorialOf(p-1);
}    

Test Passed

And the solution is as follows. Now we can use this FactorialCalculator library anywhere we want. I used in a class library named Calculator.

Solution

C#
class Program
{
    static void Main(string[] args)
    {
        Factorial calculator = new Factorial();

        for (int i = 0; i < 14; i++)
        {
            Console.WriteLine(calculator.GetFactorialOf(i));
        }
    }
}    

Console Application

Points of Interest

The most impressive aspect of TDD for me is that initially, there is no code and while test methods developing the required codes are created automatically. There is no need for planning the classes, no need to plan the variables and so on. Unnecessary operations are not implemented. We implement only requirements specification as needed. Everything is determined during the test period.

The other point is any test should not affect any other. And method implementations should not affect test results. For example, if one method is working correctly for one test, but working wrong other methods, then this is an undesired result.

Any changes of product methods require the running the tests. We did this during the application.

History

This article shows us how to create unit tests and steps of the unit testing simply. And we developed an Factorial application. After the test methods, the mainclass generated and it is ready to use. If you can see the shortcomings of the application, you can modify the methods. But any change of application requires the running tests to be on.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)