The goal of a TDD kata is to allow you to follow the red, green, refactor pattern over and over. The idea is to first write a failing test (red), write the minimum implementation to make that test pass (green) and then refactor your code as necessary to make it more maintainable / readable.
On with the kata...
Write the failing test:
1
2
3
4
5
| [Test] public void FizzBuzzer_Instantiating_ShouldNotThrowAnException() { Assert.DoesNotThrow(() => new FizzBuzzer()); } |
Write the minimum so the test will pass:
1
2
3
| public class FizzBuzzer { } |
Refactor - Nothing to refactor.
Test 2 - Value not divisible by three or five returns value
Write the failing test:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| [Test] public void Convert_ValueNotDivisibleByThreeOrFive_ShouldReturnValue() { //Arrange int valueToConvert = 1; string expectedValue = "1"; FizzBuzzer fb = new FizzBuzzer();
//Act
string result = fb.Convert(valueToConvert);
//Assert
Assert.That(result, Is.EqualTo(expectedValue));
}
|
Write the minimum so the test will pass:
1
2
3
4
| public string Convert(int valueToConvert) { return valueToConvert.ToString(); } |
Refactor - Nothing to refactor.
Test 3 - Value divisible by three returns "Fizz"
Write the failing test:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| [Test] public void Convert_ValueDivisibleByThree_ShouldReturnFizz() { //Arrange int valueToConvert = 3; string expectedValue = "Fizz"; FizzBuzzer fb = new FizzBuzzer(); //Act string result = fb.Convert(valueToConvert); //Assert Assert.That(result, Is.EqualTo(expectedValue)); } |
Write the minimum so the test will pass:
1
2
3
4
5
6
7
| public string Convert(int valueToConvert) { if (valueToConvert % 3 == 0) return "Fizz"; return valueToConvert.ToString(); } |
Refactor - There is some refactoring to be done here. There is some duplication now within the previous two tests: FizzBuzzer fb = new FizzBuzzer(); This can be extracted to a test setup method that is run before each test is executed.
Refactored test code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| private FizzBuzzer _fb; [SetUp] public void Setup() { _fb = new FizzBuzzer(); } [Test] public void Convert_ValueNotDivisibleByThreeOrFive_ShouldReturnValue() { //Arrange int valueToConvert = 1; string expectedValue = "1"; //Act string result = _fb.Convert(valueToConvert); //Assert Assert.That(result, Is.EqualTo(expectedValue)); } |
The //Act and //Assert steps within each test are also duplicated and could be extracted out into a separate method. However, to help practice the "Triple A" pattern I have chosen to leave them in each of the unit tests.
Test 4 - When value is divisible by five return "Buzz"
Write the failing test:
1
2
3
4
5
6
7
8
9
10
11
12
13
| [Test] public void Convert_ValueDivisibleByFive_ShouldReturnBuzz() { //Arrange int valueToConvert = 5; string expectedValue = "Buzz"; //Act string result = _fb.Convert(valueToConvert); //Assert Assert.That(result, Is.EqualTo(expectedValue)); } |
Write the minimum so the test will pass:
1
2
3
4
5
6
7
8
9
| public string Convert(int valueToConvert) { if (valueToConvert % 3 == 0) return "Fizz"; if (valueToConvert % 5 == 0) return "Buzz"; return valueToConvert.ToString(); } |
Refactor - Nothing to refactor
Test 5 - When a value is divisible by three and fizz return "FizzBuzz"
Write the failing test:
1
2
3
4
5
6
7
8
9
10
11
12
13
| [Test] public void Convert_ValueDivisibleByThreeAndFive_ShouldReturnFizzBuzz() { //Arrange int valueToConvert = 15; string expectedValue = "FizzBuzz"; //Act string result = _fb.Convert(valueToConvert); //Assert Assert.That(result, Is.EqualTo(expectedValue)); } |
Write the minimum so the test will pass:
1
2
3
4
5
6
7
8
9
10
11
| public string Convert(int valueToConvert) { if (valueToConvert % 3 == 0 && valueToConvert % 5 == 0) return "FizzBuzz"; if (valueToConvert % 3 == 0) return "Fizz"; if (valueToConvert % 5 == 0) return "Buzz"; return valueToConvert.ToString(); } |
Refactor - The Convert method has some duplicate modulus calculations which can be refactored and some improvements can be made to make the method more readable.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| public string Convert(int valueToConvert) { bool isFizz = valueToConvert % 3 == 0; bool isBuzz = valueToConvert % 5 == 0; if (isFizz && isBuzz) return "FizzBuzz"; if (isFizz) return "Fizz"; if (isBuzz) return "Buzz"; return valueToConvert.ToString(); } |
That completes the Fizz Buzz TDD kata.
Continuing further, you could re-factor the FizzBuzzer implementation to only use a single return statement and use the existing unit tests to confirm you have not broken any functionality. This is an important factor to remember when writing a unit test: The test should not know about any of the implementation details of what it is testing. See my blog post about a ##DDD North## session I attended to read more about this.
The projects full source code can be found here.
Fizz Buzz is an excellent problem to help you get into the TDD mindset. It allows you to focus on the red, green, refactor pattern without becoming too bogged down with implementation details. To help keep things interesting, you can also attempt many different implementations of the FizzBuzzer class when you attempt the kata.