FizzBuzz in Ruby — Following TDD

Ben Dunjay
Level Up Coding
Published in
6 min readNov 16, 2020

--

During a final stage interview recently, I was asked towards the end of my technical test if I knew FizzBuzz and if I could please implement some code to write a successful FizzBuzz script! The review of my take-home showed that I could write tests, but didn’t show my thinking, logic, and understanding of how to write tests. Now, I didn’t have long left in my test so they were more looking to see how I would tackle this particular exercise.

The concept of FizzBuzz is:

  1. You are given a number (n). This number will be your last number in your range. Starting at 1. So your range will be 1..n.
  2. If a number is divisible by 3 it will return “Fizz”.
  3. If a number is divisible by 5 it will return “Buzz”.
  4. If a number is divisible by 3 and 5 it will return “FizzBuzz”.
  5. If it isn’t divisible by any — then it returns the number.

So, if you give your number as 5. It will return — 1, 2, “Fizz”, 4 “Buzz”.

Although I didn’t have the time to fully implement the tests and code, I thought this was a pretty good exercise to practice writing clean tests.

SO, let’s begin.

I have initiated the steps to setting up a basic Ruby project for this with the necessary folders and files.

Your project should look like this.

So now we have all the necessary folders and files. Let’s tackle the next bit, TDD.

The main thing to remember about TDD is red, green, refactor.

Write a test for some functionality so that it fails. It fails because we haven’t written the code to make the test pass. You write the code to make it pass, then look to refactor, looking for any code smells without checking functionality. DRY code.

Our first test!

I like to write out what I need to do, because, in Ruby testing is written almost so it can be read like an English sentence.

  1. I need a class that takes a number put in by the user.

So, we need to write a test that checks our instance is instantiated with an argument (the number).

In our fizzbuzz_spec.rb put the below code:

Run the suite with rspec. (Because this is a small directory we can just run rspec. There are many ways to either run a particular test suite file or single test but don’t worry about that.)

Great! A failing test. Just what we want to see. Let’s go and add our code to make this pass.

This is all the code to be implemented for our test to pass. It takes a number (n, with a default value of 1), so the test will always run with a number.

Perfect, our first test. Let’s move on to more methodology.

You can add this to our initialize describe too. It essentially checks that a new instance of FizzBuzz is created with 1 argument or 0 arguments. It should work with no arguments as we put a default value.

So, let’s move onto our main method. We want to write a method that:

  1. If a number is divisible by 3 it will return “Fizz”.
  2. If a number is divisible by 5 it will return “Buzz”.
  3. If a number is divisible by 3 and 5 it will return “FizzBuzz”.
  4. If it isn’t divisible by any — then it returns the number.

So, we want to write a test that takes the number given by our instance and will make sure it's an integer by calling .to_i on it. We then want to put it into a range starting at 1, so 1..n.to_i. Then we can loop through the range to check each individual number and compare it to our above statements.

There is a lot there, so let’s break it down in our tests.

We don’t need to check the n.to_i as we know 1..n.to_i will create a range and our tests will show if they are not. We don’t need to overtest.

So remember, we want to get failing tests, get them working, then refactor. This next part is a good example of that.

Now, this is a lot of code. It’s creating a new instance in each context, then calling the method I will create on that new instance. I then was checking to see if what was returned was equal to the array at the end of each test. As you can see for divisible by 3 and 5, that is a long array.

Naturally, this was all failing. So, write the code and this is what I wrote.

Perfect, everything passes. Which is what I wanted. It’s outputting an array, where I will then have another file for running code I want to display to the user. So an array is fine.

But, looking at this. It looks like a lot of code in the test and there is a couple of things going on in the method. Maybe, I can neaten up the test suite and refactor some of the code in my method to make it neater and easier to use.

So, that’s what we shall do.

Wouldn’t it be nice to have the part of the method checking each number in another method? That way, I can use that method in the future to check any other number! I will create a method that takes a number as an argument and outputs my fizz/buzz/fizzbuzz.

So here, this is testing a method that takes a new instance with no number. Then I am passing it a method with an argument of 3. This way, I can write a test that simply checks the output of that specific number, as opposed to creating an array with the whole expected output of a range of numbers.

That might sound a little confusing. But what we want is a method that simply takes a number and checks it against the fizzbuzz methodology we had in our last method.

Here is our method. Nice and neat.

Now, that method needs a number. So let’s create a method that simply takes our input number, puts it into a range, and loops through it each time with our new method.

Amazing. IF we wanted to test that, we could simply test the output of this method and write an array. But we already know the fizzbuzz_output method tests each number correctly, so I won’t.

Okay, now for our runner.rb file, add this:

Then, when you put ruby runner.rb 15 you should get:

And our test suite with rspec.

My FizzBuzz excursion is over. Feel free to point anything out you would change, I am relatively new to this and would love further pointers if you have them.

--

--