Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

contain_exactly + a_hash_including may produce non-useful output #95

Open
mcmire opened this issue Jul 10, 2020 · 1 comment
Open

contain_exactly + a_hash_including may produce non-useful output #95

mcmire opened this issue Jul 10, 2020 · 1 comment

Comments

@mcmire
Copy link
Collaborator

mcmire commented Jul 10, 2020

When using contain_exactly against an array where some of the items in the expected array are a_hash_including, the output may not be as helpful as possible. Specifically, if one of the items in the actual array are partially matched by a item in the expected array — meaning there are some keys in the a_hash_including object that match but not others — the gem treats this as a total mismatch and will show the a_hash_including object as deleted lines in the diff. It should be able to discern that there is a partial match and delve into the actual item to show the differences. (This may apply to other matchers as well, such as include or match.)

@mcmire
Copy link
Collaborator Author

mcmire commented Feb 14, 2021

I've run into this a few times, and I think this is actually kind of difficult to address. The problem is that contain_exactly by definition represents an array whose items can appear in any order. So, even if we as developers can tell which item in the array passed to contain_exactly matches up with an item in the actual array, it's probably only because when we wrote the test, we tried to make the expected array follow as similar of an order to the actual array as possible. But I can't really bake an assumption into the differ for contain_exactly, because that assumption could very well be wrong as much as it could be right. Therefore, I think the best way to address this problem is to have the developer update the test itself so instead of using contain_exactly (or match_array, which is the same thing), explicitly place the actual array in a certain order. In other words, instead of saying this:

expect(my_cool_query).to contain_exactly(
  a_hash_including(...),
  a_hash_including(...),
  # ...
)

or this:

expect(something_that_produces_an_array).to match_array([
  a_hash_including(...),
  a_hash_including(...),
  # ...
])

it creates a better diff to say this:

sorted_array = something_that_produces_an_array.sort do |a, b|
  a[:foo] <=> b[:foo]
end

expect(sorted_array).to match([
  a_hash_including(...),
  a_hash_including(...),
  # ...
])

So that would work as a fix right now. That said... we could take a page from git's book here and implement some kind of similarity threshold. So, for each item in the contain_exactly array, compare it to each item in the actual array. If we find several where there is a, say, >= 80% similarity between the two (using fuzzy equality), then we choose the one with the highest similarity (and if there is a tiebreaker, pick the first one). Once an item in the actual array is matched, it is removed from the "pool" so that it cannot be matched again. We could even make the threshold customizable.

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

No branches or pull requests

1 participant