RSpec provides a "diff"-style output when comparing multi-line strings. Is there a way to do something similar when comparing arrays (other than converting the array to a multi-line string)?
Asked
Active
Viewed 963 times
2
-
Is [`match_array`](http://www.rubydoc.info/github/rspec/rspec-expectations/RSpec/Matchers:match_array) what you're looking for? If not, then what desired behaviour does it lack? – Tom Lord Oct 04 '17 at 13:48
-
1@TomLord `match_array` doesn't take the order of elements into account, i.e. `expect([1,2,3]).to match_array([3,2,1])` passes. – Stefan Oct 04 '17 at 13:50
-
In my case, order is important. – Zack Oct 04 '17 at 13:51
-
Oh sorry, I thought that's what you wanted. But you're actually just after a "nicer" error message when a standard `eq` matcher fails? – Tom Lord Oct 04 '17 at 13:55
-
Yes. That's exactly it. The output is long enough that it can be difficult to find the difference when the matcher fails. – Zack Oct 04 '17 at 13:57
-
What about using a custom error message? https://relishapp.com/rspec/rspec-expectations/v/3-6/docs/customized-message – mabe02 Oct 04 '17 at 13:59
-
A custom error message is a possible solution. The link you shared applies to a specific example only. I wouldn't want to repeat the customization for each example. I was also hoping to avoid having to write my own diff. (Although that is certainly not out of the question.) – Zack Oct 04 '17 at 14:04
-
The solution shown here does what I want --- except for the warning against using `RSpec::Differ` directly. https://stackoverflow.com/questions/12551564/how-to-write-a-diffable-matcher-with-rspec2 – Zack Oct 04 '17 at 14:23
1 Answers
3
I may be mistaken, but I don't think this feature is built-in to RSpec.
However, you could implement a custom matcher with a custom error message:
RSpec::Matchers.define(:eq_array) do |expected|
match { |actual| expected == actual }
failure_message do |actual|
<<~MESSAGE
expected: #{expected}
got: #{actual}
diff: #{Diffy::Diff.new(expected.to_s, actual.to_s).to_s(:color)}
MESSAGE
end
end
# Usage:
expect([1, 2, 3]).to eq_array([1, 4, 3])
This demo is using the diffy
library; you could implement this however you see fit.

Tom Lord
- 27,404
- 4
- 50
- 77
-
That's what I was looking for. The key for me was figuring out how to call the built-in differ. An older article cautioned against using the differ directly. https://stackoverflow.com/questions/12551564/how-to-write-a-diffable-matcher-with-rspec2 – Zack Oct 04 '17 at 14:50