RUBY / CHAPTER 13

Contract-focused tests and boundaries

Advanced

Use 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.

Ruby example
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"
Result
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

Chapter checkpoint

Which case detects losing duplicate positives in a filter?