Skip to content

Instantly share code, notes, and snippets.

@localshred
Last active November 22, 2023 13:27
Show Gist options
  • Save localshred/8c864db91c1252ce4386 to your computer and use it in GitHub Desktop.
Save localshred/8c864db91c1252ce4386 to your computer and use it in GitHub Desktop.
Minitest assert_equal sucks for comparing output diffs of two hashes. Using HashDiff, awesome_print, and StringIO we can get actual comparable hashes without pulling our hair out.
require "test_helper"
require "awesome_print"
require "hashdiff"
class MyClass
def self.do_stuff
{a:[{y:3}, {x:11, z:33}], b:{y:22}}
end
end
class MyClassTest < ::Minitest::Test
def test_stuff
expected = {a:[{x:2, y:3, z:4}, {x:11, y:22, z:33}], b:{x:3, z:45}}
actual = MyClass.do_stuff
diff = ::HashDiff.diff(expected, actual)
if diff.empty?
pass("Hashes are equal")
else
out = StringIO.new
grouped = diff.group_by(&:first)
if grouped["~"]
out.puts "\nDifferent Values (left, right):"
grouped["~"].each do |(_, field, left, right)|
out.puts "\t#{field}: '#{left.inspect}', '#{right.inspect}'"
end
end
if grouped["-"]
out.puts "\nMissing Values from right (left):"
grouped["-"].each do |(_, field, left)|
out.puts "\t#{field}: '#{left.inspect}'"
end
end
if grouped["+"]
out.puts "\nMissing Values from left (right):"
grouped["+"].each do |(_, field, right)|
out.puts "\t#{field}: '#{right.inspect}'"
end
end
ap_opts = { indent: 2 }
out.puts
out.puts "Expected"
out.puts "--------"
out.puts expected.ai(ap_opts)
out.puts
out.puts "Actual"
out.puts "------"
out.puts actual.ai(ap_opts)
out.rewind
flunk("Hashes are not equal:\n\n#{out.read}")
end
end
end
MyClassTest#test_stuff [/path/to/nice_hash_comparison_test.rb:56]:
Hashes are not equal:
Missing Values from right (left):
a[1].y: '22'
a[0]: '{:x=>2, :y=>3, :z=>4}'
b.x: '3'
b.z: '45'
Missing Values from left (right):
a[0]: '{:y=>3}'
b.y: '22'
Expected
--------
{
:a => [
[0] {
:x => 2,
:y => 3,
:z => 4
},
[1] {
:x => 11,
:y => 22,
:z => 33
}
],
:b => {
:x => 3,
:z => 45
}
}
Actual
------
{
:a => [
[0] {
:y => 3
},
[1] {
:x => 11,
:z => 33
}
],
:b => {
:y => 22
}
}
@fwolfst
Copy link

fwolfst commented May 22, 2019

[make_my_diffs_pretty!](https://www.rubydoc.info/github/seattlerb/minitest/Minitest%2FTest.make_my_diffs_pretty!) in test/test_helper.rb (if on Rails) does a pretty good job, though, too.

@ksnyder
Copy link

ksnyder commented Oct 17, 2020

HashDiff should be Hashdiff

@apotonick
Copy link

@fwolfst Thanks for this pointer! Didn't know about the pretty diff feature! ❤️

@mvastola
Copy link

Just came across this and it's awesome. Would you be able to declare an MIT license for it, or else declare it as public domain?

@localshred
Copy link
Author

@mvastola definitely free and available for public domain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment