Skip to content

Instantly share code, notes, and snippets.

@fabriciofreitag
Last active December 21, 2021 03:13
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save fabriciofreitag/b7458725ffef08eaf5ea541c95385a92 to your computer and use it in GitHub Desktop.
Save fabriciofreitag/b7458725ffef08eaf5ea541c95385a92 to your computer and use it in GitHub Desktop.
Custom RSPec matcher for detailed hash compasion and diff
RSpec::Matchers.define :be_a_hash_like do |expected_hash|
match do |actual_hash|
matching_results = actual_hash == expected_hash
unless matching_results
system(
"git --no-pager diff $(echo '#{JSON.pretty_generate(expected_hash)}' | git hash-object -w --stdin) " +
"$(echo '#{JSON.pretty_generate(actual_hash)}' | git hash-object -w --stdin) --word-diff",
out: $stdout,
err: :out
)
end
matching_results
end
failure_message { 'Look at the Diff above! ^^^' }
end
# then use:
expect(actual).to be_a_hash_like(expected)
@fabriciofreitag
Copy link
Author

it produces this nice output:

image

@TylerRick
Copy link

That's really clever. I didn't know you could trick git diff into being used for general purpose diffing like that!

If anyone is interested, I made a version that:

  1. Sorts hashes before comparing so that the diff only shows actual changes between keys and values (and not diffs due to accidental differences in key order, which is almost never significant in Ruby).

  2. Uses diff-so-fancy if available. While this doesn't give you a word diff, it gives a really clean line diff (using colors instead of +/- symbols). I wish I could find a way to get a word diff like that. I find the [- -]{+ +} distracting.

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