Saturday, April 10, 2010

Showing hash differences in Ruby tests

Today I was writing some tests for a Rails plugin I'm working on. The test had to compare a hash output by a method with an expected hash.

This is reasonably standard stuff - when assertion_equal failed it printed out the expected and provided data. The problem in my case was that the hashes have about 50 elements, and I only want the difference to be shown in the test output.

I knocked up this function to solve the problem, and included it in my test class:

def assert_hashes_equal(expected, actual, message=nil)
full_message = build_message(message, "Hashes were not equal, diff was:\n.\n", expected.diff(actual))
assert_block(full_message) { expected == actual }
end

So now I get this:

Hashes were not equal, diff was:
<{:plays_in_category=>"2", :dynamic_end=>"MFT", :percent_back=>"100w"}>.


Note that Hash.diff is part of Rails.

Here is what the output looks like in practice:

1) Failure:
test: SelectorImporterTest Concert Selector Parse Song 0 XML should Hashes should be equal. (SelectorImporterTest)
[/test/unit/selector_importer_test.rb:500:in `assert_hashes_equal'
/test/unit/selector_importer_test.rb:368:in `__bind_1271217771_635209'
vendor/gems/thoughtbot-shoulda-2.10.1/lib/shoulda/context.rb:253:in `call'
vendor/gems/thoughtbot-shoulda-2.10.1/lib/shoulda/context.rb:253:in `test: SelectorImporterTest Concert Selector Parse Song 0 XML should Hashes should be equal. ']:
Hashes were not equal, diff was:
<{:mood=>"3"}>.