Nested assertions with assert_difference_in_size

Some time around January of 2006, Marcel Molina, Jr. of
37signals talked briefly about a helper method he had been using for testing Ruby on Rails applications:
assert_difference_in_size. Here is the code for the method:

def assert_difference_in_size(object, methods = :count, difference = 1)
  apply = Proc.new do |obj, methods|
    [*methods].inject(object) { |result, method| result.send(method) }
  end

  initial_value = apply.call(object, methods)
  yield
  assert_equal(initial_value + difference, apply.call(object, methods))
end

The great thing about yielding to a block is that it allows you to nest calls to the method in case you’re updating multiple models in a test. For instance, I’ve got code like this at work (the
gist is that when you delete an item, the “delete” action should get logged to the parent’s log section):

def test_delete
  assert_difference_in_size(Item, :count, -1) do
    assert_difference_in_size(Log) do
      post(:delete, :id => items(:adams_car).id)
    end
  end
end

Beautiful.

Leave a Reply