-
-
Notifications
You must be signed in to change notification settings - Fork 102
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
Fix diff output when a fuzzy finder anything is inside an expected hash #599
Changes from 1 commit
b993756
4c22e70
048ac0a
c3e9ea9
416cd49
0dea769
31f086e
dd7a4c7
938096c
7046659
6b7ff69
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,8 +18,12 @@ def diff(actual, expected) | |
if any_multiline_strings?(actual, expected) | ||
diff = diff_as_string(coerce_to_string(actual), coerce_to_string(expected)) | ||
end | ||
elsif no_procs?(actual, expected) && no_numbers?(actual, expected) | ||
diff = diff_as_object(actual, expected) | ||
elsif no_procs_and_no_numbers?(actual, expected) | ||
if Hash === expected && hash_with_anything?(expected) | ||
diff = diff_as_object_with_anything(actual, expected) | ||
else | ||
diff = diff_as_object(actual, expected) | ||
end | ||
end | ||
end | ||
|
||
|
@@ -56,6 +60,13 @@ def diff_as_string(actual, expected) | |
end | ||
# rubocop:enable Metrics/MethodLength | ||
|
||
def diff_as_object_with_anything(actual, expected) | ||
expected.select { |_, v| RSpec::Mocks::ArgumentMatchers::AnyArgMatcher === v }.each_key do |k| | ||
expected[k] = actual[k] | ||
end | ||
diff_as_object(actual, expected) | ||
end | ||
|
||
def diff_as_object(actual, expected) | ||
actual_as_string = object_to_string(actual) | ||
expected_as_string = object_to_string(expected) | ||
|
@@ -73,6 +84,14 @@ def initialize(opts={}) | |
|
||
private | ||
|
||
def hash_with_anything?(arg) | ||
safely_flatten(arg).any? { |a| RSpec::Mocks::ArgumentMatchers::AnyArgMatcher === a } | ||
end | ||
|
||
def no_procs_and_no_numbers?(*args) | ||
no_procs?(args) && no_numbers?(args) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. args here will be an array of two elements? Can we check no_procs?(expected) && no_procs?(actual) && no_numbers? …. Each if those methods runs the (potentially expensive?) safe_flatten. I’d prefer this to be done just once (or, better - never!) Can’t we just take top-level keys of each of those arrays without flattening recursively? This would work on 1.8.7 |
||
end | ||
|
||
def no_procs?(*args) | ||
safely_flatten(args).none? { |a| Proc === a } | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -555,6 +555,24 @@ def inspect; "<BrokenObject>"; end | |
expect(differ.diff(false, true)).to_not be_empty | ||
end | ||
end | ||
|
||
describe "fuzzy matcher anything" do | ||
it "outputs only key value pair that triggered diff, anything_key should absorb actual value" do | ||
actual = { :fixed => "fixed", :trigger => "trigger", :anything_key => "bcdd0399-1cfe-4de1-a481-ca6b17d41ed8" } | ||
expected = { :fixed => "fixed", :trigger => "wrong", :anything_key => anything } | ||
diff = differ.diff(actual, expected) | ||
expected_diff = dedent(<<-'EOD') | ||
| | ||
|@@ -1,4 +1,4 @@ | ||
| :anything_key => "bcdd0399-1cfe-4de1-a481-ca6b17d41ed8", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now when I look at this, this is indeed and improvement to Most certainly if we’ve @JonRowe does this make sense? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you concerned by the case a 5kb json-like thing would be copied into the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe a shallow copy will not impact memory ram consumption. But what about CPU time? does Another question: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apparently, a 5kb json-like thing will impact CPU time ONLY if the matcher fails.
STEP 1 and STEP 2 will get the string representation of 5kb json-like thing in two different strings. STEP 3 will perform the comparison of both strings. This will be an expensive operation because both strings will be huge. In contrast, without the changes on this PR, comparing the string representation of this 5kb json-like thing with AFAIK, My assessment is this will impact performance only when the test fails and the developer is using a matcher that produces an output-diff. But this is my assessment about performance, I still don't know the answer to: should There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think @pirj's concern was about larger diffs, but as things should be identical the differ will often not print anything at all There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Identical - yes. But if it’s neighbouring with the difference, like the ‘anything_key’ here on line 567, and it is big, i would prefer to see the literal “anything” to be printed rather than 5kb of json. |
||
| :fixed => "fixed", | ||
|-:trigger => "wrong", | ||
|+:trigger => "trigger", | ||
| | ||
EOD | ||
expect(diff).to be_diffed_as(expected_diff) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m also struggling to understand how this works.
We do pass expected and actual there, and they end up wrapped in an array when flatten is called on it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed... that's weird... What if I remove the star operator from
#no_procs
andno_numbers
method?The purpose of this
no_procs_and_no_numbers?
method is to reduce the number of&&
operators used in the#diff
method, thus appeasing rubocop by removing theMetrics::PerceivedComplexity
offense.