RUBY / CHAPTER 13
Contract-focused tests and boundaries
AdvancedUse examples that expose wrong algorithms rather than merely exercise code.
By the end of this chapter
- Test empty and duplicate inputs
- Observe mutation separately from return values
- Distinguish expected failures from incidental exceptions
The idea
A meaningful test states a requirement and checks its observable consequence. For a stable filter, test which values remain, their order, their duplicate counts, and whether the original input changes. These are separate promises. A correct length alone cannot establish a correct result, and a correct result alone cannot establish that the caller’s data was preserved.
Boundary cases target common mistaken implementations. An all-negative maximum exposes initialization to zero, consecutive deletions expose shifting indices, and equal best candidates expose tie handling. Include an empty case when it is supported and an explicit rejection case when it is not. If a method reports invalid input with a particular exception class, check that class rather than accepting any unrelated failure as a successful test.
def keep_positive(values); values.select { |n| n>0 }; end
input=[2,-1,2,0]
result=keep_positive(input)
raise "wrong result" unless result==[2,2]
raise "mutated input" unless input==[2,-1,2,0]
puts "checks passed"checks passed
The checks preserve both repeated positive observations and the untouched original input.
Try it yourself
Design four tests for an earliest-maximum index method, including negative, tied, singleton, and empty input.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING