a better assert_difference
Courtenay : June 13th, 2006
In case you haven't seen it, assert_difference from 37s' Marcel Molina has a handy test function : (again!). Actually there are a few different versions out in the wild.. the original is from http://project.ioni.st/post/218#post-218
def test_adds_a_group
assert_difference Group, :count do
post :create, :group => { :name => 'monkeys' }
end
end
However, once you start nesting these they look like ass.
def test_membership
assert_difference Group, :count do
assert_difference User, :count do
Membership.create(:group_id => 1, :user_id => 2)
end
end
end
Here's a new way of doing it...
def test_membership
assert_difference [ User, Group ], :count do
Membership.create(:user_id => 1, :group_id => 5)
end
end
or even
test_changes_name
assert_difference User, :name, nil do
post :update, :id => 5, { :name => 'monkeys' }
end
end
paste this into your test\_helper and replace existing assert\_difference as necessary :) It's backwards compatible. And it takes strings!
def assert_difference(objects, method = nil, difference = 1)
objects = [objects].flatten
initial_values = objects.inject([]) { |sum,obj| sum << obj.send(method) }
yield
if difference.nil?
objects.each_with_index { |obj,i|
assert_not_equal initial_values[i], obj.send(method), "#{obj}##{method}"
}
else
objects.each_with_index { |obj,i|
assert_equal initial_values[i] + difference, obj.send(method), "#{obj}##{method}"
}
end
end
5 Responses to “a better assert_difference”
Sorry, comments are closed for this article.
June 14th, 2006 at 08:31 PM Courtney, That's way cool. However, I found one bug in it. I often want to test the difference in a container, say for example the :size of @group.members (where members is either a has_many or habtm association), which is an array. Now, because you flatten the array, it doesn't work anymore, because the size method is called on the member object, not the array of members.
June 15th, 2006 at 07:29 AM I second Jarkko's wish. I'm working on a version that takes a proc for the count and calls it. Theoretically you could drill down that way.
March 15th, 2007 at 05:35 PM
Thanks for the tests and ideas it gave me for further test helper development. I wanted to post a quick note about how I’ve extended this particular test to work slightly better for cached instance values.
I find myself occasionally testing to be sure some computed value has changed (counter_cache for instance, although there are several others). So, I simply added:
obj.reload if obj.respond_to?(:reload)
before both assertions (assertnotequal, assert_equal) to be sure obj.send returns any updated values.
Thanks again!
June 24th, 2007 at 02:48 PM
Buy Viagra Viagra pill Viagra Online Viagra Soft Tabs Cheap Viagra BUY CIALIS Paxil Online Buy Viagra Viagra pill Viagra Online Viagra Soft Tabs Cheap Viagra BUY CIALIS Paxil Online
July 25th, 2007 at 11:41 AM
Very useful information was found here, thank you for your work.