-
-
Notifications
You must be signed in to change notification settings - Fork 277
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
RSpec/StubbedMock should offer some rationale #1271
Comments
Original ticket. PR that introduced
There is nothing in the RSpec Style guide regarding this, but it's not uncommon:
It is common to introduce new cops and enable them in major versions, but with an exception:
I can't comment on that as I don't have this information on hand. We can harvest https://github.com/pirj/real-world-rspec to find out. Off the top of my head, I can think of: expect(User).to receive(:destroy).and_return(true)
expect(UserCreatorService.create_user).to eq(true) Changing this to Are you up for research to gather legitimate use cases for |
@odinhb Ping |
Sorry, we disabled this cop really quickly, so it's no longer bothering me. 😅 We discussed it a bit internally, and my coworker mentioned a rule (although I don't know this rule's rationale) which states there should only be a single expectation per test. Apparently this cop kinda aligns with this rule, as expecting a message to be received in addition to stubbing it to return something means there are multiple expectations. This is recommended by some other test framework as well and perhaps most interestingly, the rspec style guide also mentions it: https://rspec.rubystyle.guide/#expectation-per-example However, this style guide also says you can have multiple expectations per test if you use aggregate failures. I feel the style guide entry conflicts with this cop being enabled by default. This cop seems to be about keeping a single expectation per spec, because using I'm not sure what more research there is to do. It looks to me like the pull request you linked contained enough dissenting voices that it should've been disabled by default. I might check out the real world rspec repo, but I'm not sure what I'll find there or if it'll be of any use, and I think I'll struggle to provide rationale for a cop I disagree with. I wrote this issue with the hope that someone else could provide some rationale, so I could maybe learn something. As JonRowe said, RuboCop cops leave the impression that something is best practice, but this doesn't seem to be that. |
This rule is outdated. For the context:
Not really. The cop is more about allowing vs expecting messages with a configured response. allow(foo).to receive(:bar).with(42).and_return("hello world") # setup - doesn't count
expect(foo).to receive(:bar).with(42) # make an expectation
subject.exercise # excercise Though it will if you both make an expectation on both the received message (
As per RuboCop's practice:
RuboCop and RuboCop RSpec provide cops with configurable styles, and every so often those styles are opposite. They are enabled by default. It doesn't mean the default enforced style is the one everyone should use. E.g. # @example `EnforcedStyle: block`
# # bad
# expect { run }.to change(Foo, :bar)
#
# # good
# expect { run }.to change { Foo.bar }
#
# @example `EnforcedStyle: method_call`
# # bad
# expect { run }.to change { Foo.bar }
#
# # good
# expect { run }.to change(Foo, :bar) We usually enable cops to make them visible.
It's up to those who use RuboCop and its extensions to configure it to meet their style. Occasionally, we change cops' default enforced styles, but this is a rare case. See one such discussion as an example.
We encourage contributions, but typically people scratch their itch, and expecting someone else to fill in the gaps doesn't work. It would certainly be fantastic if every cop is linked to a style guide guideline, and those guidelines and "independent" cops provided rationales and reasoning. But the amount of work to be done is beyond the current maintainers' capacity to be done in a reasonable time. If you feel that you are personally interested in contributing a rationale for this cop - you are very welcome. Otherwise, I'm inclined to close the ticket, as this is a more generic problem than just one cop, and it's unlikely that someone would take this over with nearly 100 other open tickets. |
I don't know what the rationale is. That's why I opened this issue: someone should know why this cop exists. Otherwise it implies that the cop is arbitrary.
What do the question marks and X'ses mean? I don't entirely follow this section.
I understand wanting to ease the maintenance burden, but good defaults are important. The configurability of RuboCop is great, but the defaults it ships with still imply something. That's the reason I created this issue in the first place: I'd been searching for rationale because this cop was enabled by default, yet it seemed offensively arbitrary to me and I could not find anything other than prescriptive statements. You quoted someone earlier who was pointing out the exact same thing:
A quick and cheap solution is to disable this specific cop. |
If this cop doesn't fit your project's style - turn it off in your
Same as above.
You are welcome to open a broader issue, add a checklist and send PRs. Adding clarity to cops' descriptions and the style guide is very much appreciated. I must confess, I gave up on the idea of restoring references to old discussions for the style guide.
It is arbitrary and disabled if it suggests uncommon practices, or is yields too many false positives. I clearly see your point, but it is based on an incorrect assumption that the default configuration is ideal and fits everyone. |
Switching from expect to allow can result in a false passing test in cases where the method is no longer called. Just disable it. See rubocop/rubocop-rspec#1271
Switching from expect to allow can result in a false passing test in cases where the method is no longer called. Just disable it. See rubocop/rubocop-rspec#1271
Switching from expect to allow can result in a false passing test in cases where the method is no longer called. Just disable it. See rubocop/rubocop-rspec#1271
Switching from expect to allow can result in a false passing test in cases where the method is no longer called. Just disable it. See rubocop/rubocop-rspec#1271
Related issue: #1061
I've experienced the problem described in #1061 (where the implementation changes and there is a dangling stub) but I fail to see the point of the default (currently only) configuration of this cop.
It seems quite opinionated and should provide some example of a problem which it prevents.
Kind of like these cops do:
Some cops also link to the ruby style guide, which in turn provides the rationale, but I don't see how this cop corresponds to anything in the style guide.
Many cops are self-explanatory and there may not be any rationale for them other than consistency, but I don't think that applies to this one.
The text was updated successfully, but these errors were encountered: