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
Fail Include
matcher when comparing String with non-String
#1449
Conversation
If the actual is a String and the expected is not, a `TypeError` occurs when we try to call `actual.include?`, becuase this method expects a String when called on a String. If the actual is a `String` and the expected is not, then the match can't possibly succeed and we can return early.
In rspec/rspec-expectations#1449, the `Include` matcher is fixed so that it doesn't raise an error when types don't match. Instead, the actual and expected will be deemed to not match.
@pirj the build appears to be failing because tests that are part of rspec-rails are documenting the error that this PR fixes we probably also want rspec/rspec-rails#2728, but I'm not sure how to best sync up the two changes |
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!
Let's safeguard rspec-rails's suite from failures, and this is good to merge.
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.
Thanks for taking the time to submit this but I'm leaning towards closing this, Ruby already fails this test for us with a helpful type error, so actually this removes information from the failure, additionally if someone were to monkey patch or refine String to allow include?
to match against other things this would break that...
(Requesting changes to block merging here until I'm convinced)
@JonRowe just invert the matcher to see why this is a bug in rspec:
I think this example should pass, but it currently explodes with an error. |
I'd actually expect an error, you're matching two incompatible objects its actually a false positive for that to pass... imagine a scenario where you're gating on using the include? call, you write a test to assert that some input would cause your code to reject it and your example passes, but in production it would raise |
Thank you for the example, its actually pushed me over the fence; I'm going to close this because the false positive of this passing a negation is too much of a behaviour change, your example should fail because a production usage of that would cause an exception. |
@JonRowe I disagree, but it's your call. We'll just have to work around this behavior in our tests. Ruby is dynamically typed, and checking for inclusion in a test does not imply that we test for inclusion in production code. We are simply asserting something about the shape of the value. Here's another example that also explodes with the same error:
|
I respect your different opinion but I have to think of everyones usage and in particular the potential for the harm a false positive causes vs having to catch the error explicitly, I can appreciate its annoying to have to assert on an error vs Once again I thank you for taking the time to contribute and discuss this and I'm sorry we can't include this on this occasion. |
If the actual is a String and the expected is not, a
TypeError
occurswhen we try to call
actual.include?
, becuase this method expectsa String when called on a String.
If the actual is a
String
and the expected is not, then the matchcan't possibly succeed and we can return early.