Quantcast
Channel: : software-engineering
Viewing all articles
Browse latest Browse all 19

TDD FizzBuzz Code Kata using Machine.Specifications

$
0
0

After I read Jeff Atwood’s article claiming that some interviewees for programming jobs are unable to write even the most basic code, I thought I would have a go and see how I got on. As an extra wrinkle, I’m forcing myself to do this using strictly test driven development. I thought it might be useful to document this process and perhaps get some comments on how others might have done things differently. I’m sure mine isn’t the only way or even the best way.

The problem specification, as quoted by Jeff, is:

Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

File, New Project

This is always the scariest part of coding: starting with a blank page. So with a deep breath, here we go. Remember, test driven development, so first we create the test assembly, TiGra.CodeKata.FizzBuzz.Specifications – I’m using Machine.Specifications as my BDD/TDD framework.

using Machine.Specifications;namespace TiGra.Codekata.FizzBuzz.Specifications
{/*     * Write a program that prints the numbers from 1 to 100.     * For multiples of three print “Fizz” instead of the number.     * For the multiples of five print “Buzz”.     * For numbers which are multiples of both three and five print “FizzBuzz”.     */// Given a number, print its value.
    [Subject(typeof(FizzBuzzInteger))]publicclass when_converting_to_a_string
    {
        It should_contain_the_value_as_a_string;
    }publicstruct FizzBuzzInteger {}
}

Given the first requirement that the program prints the numbers from 1 to 100, we need to be able to have a number and print it. I could base this on integers, but I’m choosing to go with a domain specific type that wraps integer. This will allow me to override ToString() which gives me my way of printing the value. So my first test simply tests that we can have a number and obtain its value as a string.

This mandates creation of the FizzBuzzInteger class, otherwise we can’t compile. The test currently doesn’t do anything so we end up with a ‘yellow bar’:

image

Fleshing out the test a bit:

// Given a number, print its value.
    [Subject(typeof(FizzBuzzInteger))]publicclass when_converting_to_a_string
    {static FizzBuzzInteger Sut;staticstring Result;
        Establish context = () => Sut = new FizzBuzzInteger(1);
        Because of = () => Result = Sut.ToString();
        It should_contain_the_value_as_a_string = () => Result.ShouldEqual("1");
    }

This now dictates that FizzBuzzInteger needs a constructor that sets up its initial value. Note that we use ToString() that is inherited from Object, we haven’t overridden it at all at this point. The test fails though, because the constructor throws an exception. Red/Green/Refactor, baby! Lets make that red bar go green. The rules of TDD say we should do the simplest thing that makes the bar go green, so I’ll override ToString and make it return the correct value – literally. Removing that annoying exception in the constructor gives us:

publicstruct FizzBuzzInteger
    {public FizzBuzzInteger(intvalue) {}/// <summary>///   Returns the value of this instance, as a string./// </summary>/// <returns> A <see cref="T:System.String" /> containing a fully qualified type name. </returns>publicoverridestring ToString()
        {return"1";
        }
    }

Green bar. Now I need to refactor to remove duplication. The duplication here comes from the fact that I used “1” in my ToString method and also in the test. There’s no point labouring this, its obvious that I need to save the value in the constructor and use the saved value in ToString(), so here we go (the test remains unchanged):

publicstruct FizzBuzzInteger
    {readonlyint savedValue;public FizzBuzzInteger(intvalue)
        {
            savedValue = value;
        }/// <summary>///   Returns the value of this instance, as a string./// </summary>/// <returns> A <see cref="T:System.String" /> containing a fully qualified type name. </returns>publicoverridestring ToString()
        {return savedValue.ToString();
        }
    }

Still a green bar, which means I didn’t change the meaning of the code.

For multiples of three print “Fizz” instead of the number

Time for a new test. For multiples of three print “Fizz” instead of the number. Here’s the test:

    [Subject(typeof(FizzBuzzInteger))]publicclass When_converting_3_to_a_string
    {static FizzBuzzInteger Sut;staticstring Actual;
        Establish context = () => Sut = new FizzBuzzInteger(3);
        Because of = () => Actual = Sut.ToString();
        It should_contain_fizz = () => Actual.ShouldEqual("Fizz");
    }

I note that there is duplication in these tests, so I’m adding an item to my ToDo list to refactor the tests. For now though, running the test gives a red bar, much as expected:

image

Now to make that bar green. I can’t simply modify ToString() to return “Fizz” at this point, because that would break an existing test. So I have to implement a conditional test. The simplest thing I can think of is to use a modulus operator, like this:

publicoverridestring ToString()
        {if (savedValue % 3 == 0)
            {return"Fizz";
            }return savedValue.ToString();
        }

Green bar. Refactor to remove duplication – well there isn’t any at this point. Well, actually there is duplication in the tests, according to my ToDo list, so lets refactor those tests right now.

publicclass with_a_fizzbuzz_integer
    {protectedstatic FizzBuzzInteger Sut;protectedstaticstring Actual;
    }// Given a number, print its value.
    [Subject(typeof(FizzBuzzInteger))]publicclass when_converting_to_a_string : with_a_fizzbuzz_integer
    {
        Establish context = () => Sut = new FizzBuzzInteger(1);
        Because of = () => Actual = Sut.ToString();
        It should_contain_the_value_as_a_string = () => Actual.ShouldEqual("1");
    }// Given a number divisible by 3, print "Fizz"
    [Subject(typeof(FizzBuzzInteger))]publicclass When_converting_3_to_a_string : with_a_fizzbuzz_integer
    {
        Establish context = () => Sut = new FizzBuzzInteger(3);
        Because of = () => Actual = Sut.ToString();
        It should_contain_fizz = () => Actual.ShouldEqual("Fizz");
    }

Still a green bar, nothing broken. On to the next test.

For multiples of five print “Buzz”

// For multiples of five print “Buzz”.
    [Subject(typeof(FizzBuzzInteger))]publicclass When_converting_5_to_a_string : with_a_fizzbuzz_integer
    {
        Establish context = () => Sut = new FizzBuzzInteger(5);
        Because of = () => Actual = Sut.ToString();
        It should_contain_buzz = () => Actual.ShouldEqual("Buzz");
    }

Red bar. Time to add the implementation code:

publicoverridestring ToString()
        {if (savedValue%3 == 0)
            {return"Fizz";
            }if (savedValue%5 == 0)
            {return"Buzz";
            }return savedValue.ToString();
        }

And the bar is green. Is there any duplication? I can’t see any at the moment. So on to the next test.

// For numbers which are multiples of both three and five print “FizzBuzz”.
    [Subject(typeof(FizzBuzzInteger))]publicclass When_converting_15_to_a_string : with_a_fizzbuzz_integer
    {
        Establish context = () => Sut=new FizzBuzzInteger(15);
        Because of = () => Actual = Sut.ToString();
        It should_contain_fizzbuzz = () => Actual.ShouldEqual("FizzBuzz");
    }

Red bar.

image

make it go green by adding another conditional.

publicoverridestring ToString()
        {if (savedValue%3 == 0 && savedValue%5 == 0)
            {return"FizzBuzz";
            }if (savedValue%3 == 0)
            {return"Fizz";
            }if (savedValue%5 == 0)
            {return"Buzz";
            }return savedValue.ToString();
        }

That gets us our green bar. So what about duplication? I think I see some…

image

We can easily remove that using a couple of booleans, like so:

publicoverridestring ToString()
        {
            var isDivisibleBy3 = savedValue%3 == 0;
            var isDivisibleBy5 = savedValue%5 == 0;if (isDivisibleBy3 && isDivisibleBy5)return"FizzBuzz";if (isDivisibleBy3)return"Fizz";if (isDivisibleBy5)return"Buzz";return savedValue.ToString();
        }

Arguably, this last refactoring doesn’t make all that much difference, but the computation is being done once instead of twice for each multiple being tested, plus I think the code is more readable in this form. So the refactoring stands, and our bar remains green.

One test remaining.

Write a program that prints the numbers from 1 to 100

There’s not really anything to test here. I’ll need a main() function that simply has a for loop and prints 100 FizzBuzzIntegers. I could spend a long time constructing a testable main() method, but I don’t think its worth it. What really needs to happen is to create the Console Application and move the FizzBuzzInteger implementation over into its own assembly, ensuring that we don’t break any tests in the process. Without further ado, here’s the full code for the final Console Application:

using System;namespace TiGra.Codekata.FizzBuzz.ConsoleApp
{internalclass Program
    {staticvoid Main(string[] args)
        {for (int i = 1; i <= 100; i++)
            {
                var fizzBuzzInt = new FizzBuzzInteger(i);
                Console.WriteLine(fizzBuzzInt);
            }
            Console.ReadLine();
        }
    }
}

The final implementation of FizzBuzzInteger:

namespace TiGra.Codekata.FizzBuzz
{publicstruct FizzBuzzInteger
    {readonlyint savedValue;public FizzBuzzInteger(intvalue)
        {
            savedValue = value;
        }/// <summary>///   Returns the value of this instance, as a string./// </summary>/// <returns> A <see cref="T:System.String" /> containing a fully qualified type name. </returns>publicoverridestring ToString()
        {bool isDivisibleBy3 = savedValue%3 == 0;bool isDivisibleBy5 = savedValue%5 == 0;if (isDivisibleBy3 && isDivisibleBy5)return"FizzBuzz";if (isDivisibleBy3)return"Fizz";if (isDivisibleBy5)return"Buzz";return savedValue.ToString();
        }
    }
}

And finally, the final test suite:

using Machine.Specifications;namespace TiGra.Codekata.FizzBuzz.Specifications
{publicclass with_a_fizzbuzz_integer
    {protectedstatic FizzBuzzInteger Sut;protectedstaticstring Actual;
    }// Given a number, print its value.
    [Subject(typeof(FizzBuzzInteger))]publicclass when_converting_to_a_string : with_a_fizzbuzz_integer
    {
        Establish context = () => Sut = new FizzBuzzInteger(1);
        Because of = () => Actual = Sut.ToString();
        It should_contain_the_value_as_a_string = () => Actual.ShouldEqual("1");
    }// Given a number divisible by 3, print "Fizz"
    [Subject(typeof(FizzBuzzInteger))]publicclass When_converting_3_to_a_string : with_a_fizzbuzz_integer
    {
        Establish context = () => Sut = new FizzBuzzInteger(3);
        Because of = () => Actual = Sut.ToString();
        It should_contain_fizz = () => Actual.ShouldEqual("Fizz");
    }// For multiples of five print “Buzz”.
    [Subject(typeof(FizzBuzzInteger))]publicclass When_converting_5_to_a_string : with_a_fizzbuzz_integer
    {
        Establish context = () => Sut = new FizzBuzzInteger(5);
        Because of = () => Actual = Sut.ToString();
        It should_contain_buzz = () => Actual.ShouldEqual("Buzz");
    }// For numbers which are multiples of both three and five print “FizzBuzz”.
    [Subject(typeof(FizzBuzzInteger))]publicclass When_converting_15_to_a_string : with_a_fizzbuzz_integer
    {
        Establish context = () => Sut = new FizzBuzzInteger(15);
        Because of = () => Actual = Sut.ToString();
        It should_contain_fizzbuzz = () => Actual.ShouldEqual("FizzBuzz");
    }
}

The Visual Studio solution looks like this:

image

We have a green bar, so I’m confident this program is bug free.

image

Here’s the output:

image


Viewing all articles
Browse latest Browse all 19

Trending Articles