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
Switch to receive
message expectation syntax
#7067
Switch to receive
message expectation syntax
#7067
Conversation
This line: expect(formatter_set).to all(have_received(:started).with(files)) previously was expect(formatter_set).to all(receive(:started).with(files)) but was triggering a RSpec/SubjectStub offence, and there was a special case treatment introduced to `rubocop-rspec` to relax detection of stubbing when `all` matcher is used together with a message expectation matcher. The cop is not at the moment able to detect `have_received` matcher, but there is an open pull request to improve the detection. That pull request (rubocop/rubocop-rspec#770) is also aiming to remove that special case treatment, because, as experiment has shown, across [`real-world-ruby-apps`](https://github.com/jeromedalbert/real-world-ruby-apps) and [`real-world-rails`](https://github.com/eliotsykes/real-world-rails), there is no other offences detected apart from this `FormatterSet` spec. In any case, the rest of the spec don't use `all`, and are explicit of which object the expectation is made against (by using `[0]`, `[1]`). Also, using spies is not justified in this case. It doesn't make much sense to use a `before` hook that is only run along with a single example.
Base formatter spec was actually testing how the runner is calling the formatter, so the subject of it is different.
Nicely done! Thanks! |
😢 I find the main benefit of using After this PR, the |
@bquorning I had doubts about this change as well, but looking at the changes one by one I was more inclined to do this change rather than keep things as is:
- allow(File).to receive(:open).and_call_original
+ expect(File).not_to receive(:open).with(%r{/ignored/})
expect(cli.run(%w[--format simple example])).to eq(0)
expect($stdout.string).to eq(<<~OUTPUT)
0 files inspected, no offenses detected
OUTPUT
- expect(File).not_to have_received(:open).with(%r{/ignored/}) There was (and still is) no clear Act/Excercise stage, it was mixed with value comparison expectation in a single statement. The combination of A necessity to
There is no Arrange/Setup phase. To avoid incidental state (more like behaviour than a state), a block style expectation could be used, e.g. It reads better, a hook is not used. Also, I would disagree that setting up a spy counts towards the Setup/Arrange phase. With swapping two parts of the example, e.g.
Both sentences read quite similarly, and I hope the examples as well. Verified doubles are not used, incidental behaviour might strike, since there are at least two statements in Act/Excercise phase,
Can't disagree with this. Found two cases in this pull request, 1 (mentioned earlier and 2. I can imagine an example where a number of message expectations are sent, and then the results are compared to the reference expected values. Hiding the Act/Excercise phase in a hook is a bad practice, and this pull request changes this by making a call to I really respect AAA or 4PT, but the usages of message spies that were changed in this specific pull request did not look like a canonical example of it. Went through the changes once again. I might have a bias for this since my goal was to get rid of message spy without breaking |
I started off improving
RSpec/SubjectStub
cop that had a special case of dealing withexpect(subject).to all receive(...)
that was originally present in RuboCop, and I've removed this special case in this commit, since according to an experiment, it's not raising any single offence for repositories fromreal-world-ruby-apps
(11k files) andreal-world-rails
(79k files).Original line when a special case was introduced:
later reworked to:
I've replaced this with:
that is quite consistent with the style used in the rest of that spec file.
Also, using spies is not justified in this case.
It doesn't make much sense to use a
before
hook that is only run along with a single example, so I've simplified it as well.However, I've faced another cop,
RSpec/MessageSpies
, that complains thatreceive
is used instead ofhave_received
. What confuses me is that according to the chat from 10 Oct 2016:However, in
rubocop
this is not a problem, as multiple expectations per example are allowed:So I decided to give it a shot and take a look what happens if I switch the default enforced style of
RSpec/MessageSpies
fromhave_received
toreceive
, and this pull request is the result of this switch.Why it makes sense to merge this?
rubocop-rspec
'sSubjectStub
has a special case that deals with a single known example, here, inrubocop
'sformatter_set_spec.rb
.Why it wouldn't make sense to merge this?
expect(...).to receive
breaks Arrange-Act-Assert pattern.What is redundant
I've made a couple of changes along the way not directly related to this change, specifically changed
receive { ... }
to.and_return
. Don't remember the details, but I think it's recommended to use this syntax.Appreciate any feedback on this.
Before submitting the PR make sure the following are checked:
[Fix #issue-number]
(if the related issue exists).master
(if not - rebase it).and description in grammatically correct, complete sentences.
bundle exec rake default
. It executes all tests and RuboCop for itself, and generates the documentation.