Designing for Testability
Describing testing with the phrase “Red, Green, Refactor” makes it seem fairly straightforward. Most people interpret this as the process of writing some failing tests, getting those tests to pass, and then cleaning up the code without causing the tests to fail again. This general assumption is exactly correct, but a common misconception is how much work needs to be done between each phase of this cycle.
For example, if we try to solve our whole problem all in one big chunk, add tests to verify that it works, then clean up our code, we end up with implementations that are very difficult to test, and even more challenging to refactor. The following example illustrates just how bad this problem can get if you’re not careful. It’s from some payroll management code I wrote in a hurry a couple of years ago:
def time_data_for_week(week_data,start,employee_id) data = Hash.new { |h,k| h[k] = Hash.new } %w[M T W TH F S].zip((0..6).to_a).each do |day,offset| date = (start + offset.days).beginning_of_day data[day][:lunch_hours] = LunchTime.find(:all, conditions: ["employee_id = ? and day between ? and ?", employee_id, date, date + 1.day - 1.second] ).inject(0) { |s,r| s + r.duration } times = [[:sick_hours , "Sick" ], [:personal_hours, "Personal"], [:vacation_hours, "Vacation"], [:other_hours, "Other" ]] times.each do |a,b| data[day][a] = OtherTime.find(:all, conditions: ["employee_id = ? and category = '#{b}' and date between ? and ?", employee_id, date, date + 1.day ...Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access