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
Make be_predicate fail upon calling a private method #207
Make be_predicate fail upon calling a private method #207
Conversation
@JonRowe -- thanks for taking a stab at this. I've been meaning to respond to #206. I share many of the questions you mentioned above! Anyhow, let's take the conversation back to #206 where we can figure out the overall strategy to solve this, and then, if it lines up with what you've done here, we can return to this PR to discuss any remaining implementation concerns. |
""" | ||
When I run `rspec attempting_to_match_private_method_spec.rb` | ||
Then the output should contain "1 example, 1 failure" | ||
And the output should contain "expected secret? to return true, but it's a private method" |
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 think this message should clarify that private methods are not accessible in expectations. It might seem obvious to some, but it reads (to me) like "I was trying to make a left turn, but I was thirsty" (the "but" being somewhat orthogonal to the expectation).
In normal use, calling privates from the outside results in an error e.g.
NoMethodError: private method `print' called for "this":String
Why not treat these as errors as well, e.g.
NoMethodError: private method `print' called for "this":String (expectations on private methods are not supported)
Or even take it a step further:
UnsupportedOperationError: expectation set on private method `print' for "this":String
I've taken your feedback to heart, and am raising an error with a message, which actually cleans up the resulting failure messages again, however on 1.8.7 I'm now getting weird |
@JonRowe no idea :( I've never understood why that happens. |
Just re-run today and they work, from a bit of googling seems this is a "weird" Heisenbug which is platform dependant... So this passes on 1.8.7 and 1.9.3 |
So my feeling here is this might be a travis weirdness, can we force it to rerun the build? |
We can do, but I have experienced the failure locally, it's a weird Ruby heisenbug... |
I rebased this, so let's see what happens to the build. |
Woo, passes |
@JonRowe I think this needs a changelog entry, but is otherwise pretty awesome. Could you add one? 👍 💚 : |
This can't be merged until 3.0, because it'll be a breaking change. It's definitely a good change, though! |
That too :) |
@@ -135,6 +135,9 @@ def initialize(*args, &block) | |||
|
|||
def matches?(actual) | |||
@actual = actual | |||
|
|||
raise "UnsupportedOperationError: expectation set on private method `#{predicate}`" if actual.private_methods.include?(predicate.to_sym) || actual.private_methods.include?(predicate.to_s) |
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.
- This line is super long, particularly for having a trailing
if
. I'd prefer to see the non-trailing if for a case like this. - Rather than including handling for both 1.8 and 1.9 in a single line, I'd prefer to see something like:
if methods.first.is_a?(String)
def private_method_on?(object)
object.private_methods.include?(predicate.to_s)
end
else
def private_method_on?(object)
object.private_methods.include?(predicate.to_sym)
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've refactored this, take a look when you have a sec.
@JonRowe want to merge this in now we're doing 3.0 on master? |
I thought that was after the 2.14.0 final release. Correct? No? |
That's what I was pushing for on the mailing list. I think master should be 2.14 until we actually ship 2.14 and not just an rc. /cc @myronmarston @soulcutter |
@dchelimsky 2.14 dev is on the maintenance branch now. @myronmarston @alindeman and myself were chatting about this last night on irc. The 2.99 maintenance branch also exists. |
No sense going back :) On Tue, May 28, 2013 at 6:29 PM, Sam Phippen notifications@github.comwrote:
|
I'm going to look at this and merge it tonight |
@@ -135,6 +135,9 @@ def initialize(*args, &block) | |||
|
|||
def matches?(actual) | |||
@actual = actual | |||
|
|||
raise "UnsupportedOperationError: expectation set on private method `#{predicate}`" if is_private_on?( @actual ) |
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.
How about making an UnsupportedOperationError
class? Raising a RuntimeError
with a message that suggests it is a different kind of error feels odd to me.
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 like this. 🐑 it. |
@@ -31,6 +31,18 @@ | |||
}.to raise_error(NameError, /happy\?/) | |||
end | |||
|
|||
it 'fails when :predicate? is private' do | |||
klass = Class.new 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.
Just for grins: I'd name this class privately_happy
and have happy?
return true
:)
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.
On your head be it... ;) I totally did not indulge my own humour in the commit 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.
:)
…vate Make be_predicate fail upon calling a private method
A potential solution to #206, this makes
be_predicate
fail with a nice warning when calling a private methods.Potentially this might want to be configurable, so as not to break existing test suites? Is this a decision we want to make for the person writing the test suite? Is #206 the desired behaviour or do we want to let users make the decision about calling private methods...