All PRs
On my last Ruby job, I had to do many integrations with third party services. These services were sending big hashes to the app, and I was the only one in the team understanding what these hashes represents in the real world. That’s why I submitted an enhancement to the RSpec anything fuzzy matcher diff.
I had to rely heavily on a good test suite and fixtures, otherwise the work would have been very tedious and cumbersome. Furthermore, having fixtures will help my colleagues understand what is happening on the integration process if something goes wrong and I am not available anymore.
My workflow was great, because I was using the match
matcher to compare hashes. If anything goes wrong, the matcher would tell me which key-value pair is either missing, extra or different in the diff message.
But things started to get complicated when I added the anything
fuzzy matcher in my big fixtures. In order to have my test suite tidy, clean and readable, I worked with JSON files containing fixtures and made a helper function to replace these unimportant values (eg: ids and timestamps) with the anything
fuzzy matcher inside my tests. Everything was doing fine… until errors appeared on my iterations while working on my feature requests.
Let’s see an example before I explain the content of my PR
Suppose you have this hash inside a fixture file you are going to use it as the expected value

If the actual value you receive in your test has a different timezone (eg: America/Lima) you will see this on your terminal when the test fails.

Cool! The matcher is doing its work. But what happens when you use the anything
fuzzy matcher to scrub the unimportant values you want to be there but don’t care about their value (“id”, “createdAt” and “updatedAt”)?

Note the only wrong value is the “timezone”: all other values are correct. The diff output shows you there are four wrong instead of only one. If the timezone is correct, the test passes and there is no diff output. Worst thing is when you have nested hashes (I will spare you the screenshot example on that case)
Using the anything
fuzzy matcher seems to be a drawback: I have my fixtures representing data coming from the real world (with fake ids, of course), I am scrubbing the irrelevant data with anything
, I am using the right RSpec matcher to compare hashes… but if something goes wrong on my application code, I’ll have to find the needle in a haystack even though I am using the right tools.
The Solution
I thought about a simple solution: What if I find the class responsible to write the diff, take the expected value argument and substitute every anything
object by a copy of the actual value?
I found the class and implemented the idea. Best part is the copy in the expected value lives only in the scope of the differ.
After discussing and analyzing my solution on the PR thread, the maintainers accepted my solution and it was merged into the repository.