Computed tests
What if you have lots and lots of methods in lots of classes, and you want to make changes to them? You’d need to output a lot of things, and inspect them very carefully, in order not to miss any mistakes.
In the example above you’d have to remember that your code is valid if it
outputs false
for the first two years, and true
for the last two ones.
That’s a lot of knowledge to keep in mind for just one method. Imagine you’d
have hundreds of methods. You’d need to very carefully inspect a lot of output.
Isn’t that what computers are there for? Doing all the tedious, mechanical work for us that requires a lot of precision?
Let’s see. What if we, instead of outputting plain values to the terminal, also output a hint if this is the value that we expected to see?
def leap_year?(year)
year % 400 == 0 or year % 100 != 0 and year % 4 == 0
end
if $0 == __FILE__
data = {
2001 => false,
1900 => false,
2000 => true,
2004 => true
}
data.each do |year, expected|
actual = leap_year?(year)
if expected == actual
puts "leap_year?(#{year}) returned #{actual} as expected."
else
puts "KAPUTT! leap_year?(#{year}) did not return #{expected} as expected, but actually returned #{actual}."
end
end
end
This will output:
leap_year?(2001) returned false as expected.
leap_year?(1900) returned false as expected.
leap_year?(2000) returned true as expected.
leap_year?(2004) returned true as expected.
Let’s try breaking our method by always returning true
:
def leap_year?(year)
true
end
We’ll then get:
KAPUTT! leap_year?(2001) did not return false as expected, but actually returned true.
KAPUTT! leap_year?(1900) did not return false as expected, but actually returned true.
leap_year?(2000) returned true as expected.
leap_year?(2004) returned true as expected.
That’s much better, isn’t it? Even if you’d have hundreds of tests (many real-world applications do have thousands) it would be pretty easy to spot any broken behavior, right?