TLDR; Four JUnit @Test methods to create a FizzBuzz solution using Test Driven Development (TDD) with Java Junit.
TDD Exercise - FizzBuzz
As part of a Sunday Morning practice session I used FizzBuzz as my coding exercise.
I’ve heard that this is used in programming interviews and I so I thought I’d try it.
FizzBuzz rules are documented here http://wiki.c2.com/?FizzBuzzTest
The video I created of the TDD session is at the bottom of this post.
First I:
- created a test class
- copied in the rules as a comment
- formatted the rules to make it easy to understand
- added some examples so that I could understand
My First Test
The first Test I wrote was:
@Test
public void fizzBuzzConvertorLeavesNormalNumbersAlone(){
FizzBuzzConverter fizzBuzz = new FizzBuzzConverter();
Assert.assertEquals("1", fizzBuzz.convert(1));
}
This forced me to create the FizzBuzzConverter
class and convert
method.
I added a second assertion to this test:
Assert.assertEquals("2", fizzBuzz.convert(2));
This forced me to actually implement the default code in convert:
return String.valueOf(toConvertToFizzBuzz);
Thoughts on My First Test
Some people don’t like multiple assertions in a Test.
Sometimes I do, sometimes I don’t.
Here, I didn’t mind:
- the test name allowed me to have multiple assertions
- I thought multiple test methods would make it harder to Grok
My Second Test
The second test was:
@Test
public void fizzBuzzConvertorMultiplesOfThree(){
FizzBuzzConverter fizzBuzz = new FizzBuzzConverter();
Assert.assertEquals("Fizz", fizzBuzz.convert(3));
}
This forced me to implement the ‘3’ division rule:
if(toConvertToFizzBuzz%3==0){
return "Fizz";
}
I imagine that if you don’t know the modulus operator then FizzBuzz can be quite hard.
I learned modulus back in the day of 8 bit programming and have been using it for various boundary, clipping, and scrolling routines ever since.
My Third Test
The third test was:
@Test
public void fizzBuzzConvertorMultiplesOfFive(){
FizzBuzzConverter fizzBuzz = new FizzBuzzConverter();
Assert.assertEquals("Buzz", fizzBuzz.convert(5));
}
Much the same as the condition for number 3:
if(toConvertToFizzBuzz%5==0){
return "Buzz";
}
At this point my convert
method looks as follows:
public String convert(int toConvertToFizzBuzz) {
if(toConvertToFizzBuzz%5==0){
return "Buzz";
}
if(toConvertToFizzBuzz%3==0){
return "Fizz";
}
return String.valueOf(toConvertToFizzBuzz);
}
Thoughts on Test 3
I have seen people create very complicated code for FizzBuzz.
I’m keeping it simple on the basis that. If I can get it working, then I can refactor it for efficiency or ’looking like a good programmer’ later.
Test 4
My Fourth Test was much the same.
@Test
public void multiplesOfBothThreeAndFive(){
FizzBuzzConverter fizzBuzz = new FizzBuzzConverter();
Assert.assertEquals("FizzBuzz", fizzBuzz.convert(15));
}
At this point though, when I looked at the convert method I started to think:
- should I add a flag to check for fizz and buzz?
- should I have a set of nested ifs?
- perhaps I can use a tertiary operator for some ‘magic’
Instead I decided to keep it simple:
if(toConvertToFizzBuzz%15==0){
return "FizzBuzz";
}
Thoughts on Test 4
I suspect that this is the point at which people ‘fail’ to implement FizzBuzz, because the code in the method becomes over complicated.
My @Test
methods do not warrant any complicated code:
public String convert(int toConvertToFizzBuzz) {
if(toConvertToFizzBuzz%15==0){
return "FizzBuzz";
}
if(toConvertToFizzBuzz%5==0){
return "Buzz";
}
if(toConvertToFizzBuzz%3==0){
return "Fizz";
}
return String.valueOf(toConvertToFizzBuzz);
}
There is a priority to the conditions where:
- 15 is higher priority because it is a combination of 3 and 5
- 3 and 5 are equal priority and so it doesn’t matter which order they are in
- String conversion is the default so is lower priority
In olden days we were taught to have a single return value per method. If I had written the code this way then it would be more complicated. Instead I return
as soon as I’ve matched a condition.
The conditions are really as set of ‘guards’ to prevent fall through to the default operation.
Done
At this point I’m ‘done’.
Or at least I have an algorithm that will support the conversion of integers in the range 1 to 100 into Fizz, Buzz, Number or FizzBuzz
All I have to do is wrap it into something that will print out the values.
@Test
public void outputTheHundredFizzBuzzes(){
FizzBuzzConverter fizzBuzz = new FizzBuzzConverter();
for(int i=1; i<=100; i++){
System.out.println(fizzBuzz.convert(i));
}
}
I created it as an @Test
for expediency and I can execute it from the IDE.
And then the tester kicks in
- I have used TDD to design the algorithm.
- I have not ’tested’ the output routine, I have executed it and seen the output from 1-100, but I don’t really have an Oracle to compare that to
- I haven’t asserted on my acceptance criteria but I have seen the values match my output from running
outputTheHundredFizzBuzzes
If this was a programming interview I might have to convert the outputTheHundredFizzBuzzes
into a main
method and run it, but the basic implementation of the requirements have been met.
As a tester I’m not sure I have convinced myself it ‘works’, but it ‘works’.
You can find all the code for this in the repo https://github.com/eviltester/fizzbuzz