Archive for

May 2007

Short Feedback Loops

Short positive feedback loops in software development are important.

Looking at what happened in the past, we can suggest what could be done to improve the situation in the future. It’s fundamental to lean and agile methodologies. Indeed, the methodologies themselves encourage adaptation of the methodologies by teams to adapt the practices and processes locally.

Test Driven Development (and it’s variants and corollaries) are all about this feedback, they help you think about what you’re doing immediately by showing you straight away. For instance, you can decide there and then that you don’t like the name of something (perhaps it turns out it doesn’t describe the intent). Feedback from you using your code can improve how you design your code.

People strive for fast running tests - they help keep developers upbeat. Slow builds sap the patience and take focus away from writing code and introduce unnecessary context switching. Slow tests become a pain, and people find ways to try and get around having to run them. Feedback is discarded.

To my mind, this is exactly why trying to split off the writing of tests to separate developers is costly - tests are a valuable learning tool, they provide a continuous response to you.

Write a nice clean test that results in simple and expressive code feels good, bad test phrasing feels dirty. Take yourself away from the feedback and you lose the opportunity to gain those insights. It may be that you spend most of your time working with developer tests, but having acceptance tests up-front that can direct your effort provide a great communication tool.

Keep yourself close to the feedback.

Posted

A Neat Little Rails Testing Pattern

Inside my tests I try and keep everything I need inside the test, rather than depending on too many fixtures. That way I ensure they’re as readable as possible, and more importantly, obvious.

But, take the following example:

def test_total_is_due_now_if_return_is_less_than_14_days  booking = Booking.new(    :customer => customers(:valerie),    :collect_at => 1.day.from_now.to_date,    :return_at => 13.days.from_now.to_date,    :boxes => 2,    :collection_address => addresses(:one))  assert_equal Date.today.to_s, booking.final_payment_due_date.to_senddef test_payment_due_14_days_from_now  booking = Booking.new(    :customer => customers(:valerie),    :collect_at => 1.day.from_now.to_date,    :return_at => 20.days.from_now.to_date,    :boxes => 2,    :collection_address => addresses(:one))
  assert_equal 6.days.from_now.to_date.to_s, booking.final_payment_due_date.to_send

Well, everything’s in the test, but there’s a fair bit of duplication. What would be nicer, is to take the prototype booking above and just override certain values.

Instead we might write something like

def test_total_is_due_now_if_return_is_less_than_14_days  booking = new_booking_with(:return_at => 13.days.from_now.to_date)  assert_equal Date.today.to_s, booking.final_payment_due_date.to_senddef test_payment_due_14_days_from_now  booking = new_booking_with(:return_at => 20.days.from_now.to_date)  assert_equal 6.days.from_now.to_date.to_s, booking.final_payment_due_date.to_send
privatedef new_booking_with(args)  Booking.new(args.reverse_merge({    :customer => customers(:valerie),    :collect_at => 1.day.from_now.to_date,    :return_at => 15.days.from_now.to_date,    :boxes => 2,    :collection_address => addresses(:one)  }))end

Much nicer (to me anyway), particularly once you start adding more and more tests (and especially validation related ones).

Posted
Fork me on GitHub