-
-
Notifications
You must be signed in to change notification settings - Fork 395
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
Give correct error message for expect {}.not_to raise_error(/foo/)
#1456
Give correct error message for expect {}.not_to raise_error(/foo/)
#1456
Conversation
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.
No objections on the changes, just a few notes to spark a discussion on if this can be further improved. Partially caused by the lack of morning coffee.
expect { raise 'blarg' }.not_to raise_error("blah") | ||
end | ||
|
||
it "can supresses the warning when configured to do so", :warn_about_potential_false_positives do |
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.
Wondering why ‘warn_about_potential_false_positives’ metadata is needed here to warn, but it warns anyway in other examples? Is it to restore the setting to the default? It just reads confusingly when used this way.
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 see that we do the same in other examples in this file.
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 didn't know about this until you asked (and I wasn't sure until I tested it out), but adding a shared context like this one (with a tag specified) causes that context to be automatically included in any context that supplies that same tag. So including this metadata causes an automatic cleanup to occur. I, of course, had just copied it from other tests without thinking :-)
@@ -25,7 +25,7 @@ def initialize(expected_error_or_message, expected_message, &block) | |||
when nil, UndefinedValue | |||
@expected_error = Exception | |||
@expected_message = expected_message | |||
when String | |||
when String, Regexp |
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.
Is there any change in behaviour?
Is looks like that previously a regexp would have been used as an exception?
This change indeed seems the right thing to do. I’m wondering, why it worked the same way before?
Is it because we still were tolerant to whatever it is an exception or something matcheable with a string message?
if values_match?(@expected_error, @actual_error) ||
values_match?(@expected_error, actual_error_message)
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.
So.. there is a change in "behavior", but it pretty much just affects what failure messages come out. These two ivars are really only used for that purpose, and aren't exposed externally, thankfully; the only impact I can find is that a slightly wrong failure message gets generated (it acts as though you supplied an exception if you supplied only a regex). Could have had larger impact, but the main place we look at the @expected_error
, we only check @expected_error != Exception
, which is not true for Regexps either (though I suppose if you supplied to raise_error(Exception, /foo/)
, you might also be able to get some wrong behavior?).
And the reason the specs didn't mind was just that the case checking this had a test that only checked the part of the failure message the outcomes had in common ("risks false positives"), which was still being produced.
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.
Thank you!
RSpec.describe "expect { ... }.not_to raise_error(/message/)" do | ||
it "issues a warning when configured to do so", :warn_about_potential_false_positives do | ||
RSpec::Expectations.configuration.warn_about_potential_false_positives = true | ||
expect_warning_with_call_site __FILE__, __LINE__+1, /not_to raise_error\(message\)` risks false positives/ |
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.
Just to dissect it. Before the change, this was printing a slightly different warning:
Using `expect { }.not_to raise_error(SpecificErrorClass)` risks false positives
and now it's a more appropriate for not_to raise_error(/regexp/)
:
Using `expect { }.not_to raise_error(message)` risks false positives
My apologies that it took that long to figure out.
And split off a pair for the String case (versus the Regexp case, since that was the critical difference in the code here)
If the first argument is a Regexp, it's a message _matcher_, rather than a message.. but certainly it's not an exception! I'm actually a bit surprised this doesn't cause any other problems, but it doesn't seem to.
this confused us at a glance, and it probably will again later
f85ca83
to
32ea28c
Compare
…regex-not-raise-case Give correct error message for `expect {}.not_to raise_error(/foo/)`
Released in 3.13.1 |
Found this while adding coverage - there was a test that ought to have covered the line in question, but didn't because it was actually slightly too loose. Tightening it up shows that it's getting the wrong error message, because the RaiseError matcher is handling
expected_error_or_message
by checking the type, and it's looking for String, but not Regexp there.Figured it'd make more sense as its own PR, since it's not just test coverage. (The line is covered afterwards though!)
Failure with just the test change: