I have a very simple Ruby implementation of a game called "FizzBuzz" (i.e. given an input number, it returns "Fizz" if the number is multiple of 3, "Buzz" if multiple of 5, "FizzBuzz" if multiple of both and the original number if it doesn't fit any of the previous condition):
class FizzBuzz
def answer(number)
multiple3 = number%3 == 0
multiple5 = number%5 == 0
return case
when (multiple3 and multiple5) then "FizzBuzz"
when multiple3 then "Fizz"
when multiple5 then "Buzz"
else number
end
end
end
I wrote a test using RSpec to validate each one of the conditions:
require "rspec"
require "./fizzBuzz"
RSpec.describe "#answer" do
it "returns Buzz when number is multiple of 3" do
result = FizzBuzz.new.answer(3)
expect(result).to eq("Fizz")
end
it "returns Buzz when number is multiple of 5" do
result = FizzBuzz.new.answer(5)
expect(result).to eq("Buzz")
end
it "returns a number when the input number is neither multiple of 3 nor 5" do
result = FizzBuzz.new.answer(11)
expect(result).to eq(11)
end
end
The test works perfectly, however, I'm using concrete values in it (i.e. 3, 5 and 11).
My question is: what if I wanted to test my FizzBuzz Ruby script using a wide range of values (e.g. from 1 to 10000)?
I know I can solve this by using each loops and cases directly in RSpec, however, my concern is that if in my test I adopt the same conditional statements as in the Ruby script to be tested (i.e. when number%3 == 0 then "Fizz"
, etc.) I will end up testing my code using an RSpec script that follows exactly the same logic as the script to be tested, hence the test will probably pass successfully.
What would be the alternative? Are there best practices to write tests using a wide pool of values (e.g. using a loop) rather than hard-coded or specific values?