-
-
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
Add RSpec/NoExpectationExample
#1321
Conversation
Sorry I haven't read the related issues at all. I see that we had the same discussion a few days ago and even 10 years ago. It's just a coincidence that I created this pull request today. |
f9c5b23
to
1432383
Compare
Thanks for the review comments! I learned a lot of information I didn't know 👍 |
b05886d
to
4db2c25
Compare
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 don't feel that this cop should implement autocorrection. WDYT?
# @param [RuboCop::AST::Node] node | ||
# @return [Boolean] | ||
def including_any_expectation?(node) | ||
if !node.is_a?(::RuboCop::AST::Node) |
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.
What else can it be?
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.
For example, if the parent node is s(:send, nil, :it)
, its children are [nil, :it]
, so it can be nil or a Symbol.
I'm on the fence about that.
I actually used this cop's autocorrection in my Rails app because I had to change a large amount of code there, but I am thinking that maybe this autocorrection should be removed. |
I think an empty example group has more chances to be a deliberate choice than the no expectations one. The latter is most likely a mistake. it { subject } # Just checks if calling `subject` doesn't raise any exceptions it { validates_presence_of(:attribute) } # Oops, missing `is_expected.to` It would be quite odd to remove those examples.
I have to agree with this, unfortunately, with the
I fully support that. Let me quickly run the cop against several codebases in |
I briefly went through, and tried categorizing cases that look like false positive/suspicious:
# /Users/pirj/source/real-world-rspec/loomio/spec/models/user_spec.rb
it "returns the stored name if deactivated_at is nil" do
user.name.should_not == 'Deleted user'
end # /Users/pirj/source/real-world-rspec/rspec-mocks/spec/rspec/mocks/configuration_spec.rb
it "does not warn about the should syntax" do
RSpec.should_not_receive(:deprecate)
Object.new.should_not_receive(:bees)
end
# /Users/pirj/source/real-world-rspec/mastodon/spec/controllers/auth/registrations_controller_spec.rb
it 'does nothing if user already exists' do
Fabricate(:account, username: 'test')
subject # Frankly, I'm struggling to understand where `subject` is defined
end # /Users/pirj/source/real-world-rspec/refinerycms/pages/spec/models/refinery/page_meta_data_spec.rb
it 'meta_description' do
page.respond_to?(:meta_description) # should be `expect(page).to respond_to(:meta_description)` ?
end
it 'tracks when sign in is nil' do
user.update(current_sign_in_at: nil)
sign_in user, scope: :user
get :show
expect_updated_sign_in_at(user)
end
it "updates the requested expense" do
expense = Expense.create! valid_attributes
put :update, {:id => expense.to_param, :expense => new_attributes}, valid_session
expense.reload
skip("Add assertions for updated state")
end
# /Users/pirj/source/real-world-rspec/publify/publify_core/spec/controllers/admin/articles_controller_spec.rb
it "sends notifications on create" do
u = create(:user, notify_via_email: true, notify_on_new_articles: true)
u.save!
ActionMailer::Base.deliveries.clear
emails = ActionMailer::Base.deliveries
post :create, params: { "article" => base_article }
assert_equal(1, emails.size)
assert_equal(u.email, emails.first.to[0])
end
# /Users/pirj/source/real-world-rspec/puppet/acceptance/lib/puppet/acceptance/classifier_utils_spec.rb
it "provides a handle to the classifier service" do
handle.expects(:perform_request).with(Net::HTTP::Get, '/hi', {})
handle.get('/hi')
end
# /Users/pirj/source/real-world-rspec/rspec-core/spec/rspec/core/backtrace_formatter_spec.rb
it "deals gracefully with a security error" do
Metadata.instance_eval { @relative_path_regex = nil }
with_safe_set_to_level_that_triggers_security_errors do
self.formatter.__send__(:backtrace_line, __FILE__)
# on some rubies, this doesn't raise a SecurityError; this test just
# assures that if it *does* raise an error, the error is caught inside
end
end
# /Users/pirj/source/real-world-rspec/rspec-core/spec/rspec/core/configuration_spec.rb
it 'successfully invokes the block' do
RSpec.describe("group") { it "example 1" do; end}
example = RSpec.world.example_groups.first.examples.first
expect(example.metadata[:new_key]).to eq(:new_value)
end
it 'does not register any offenses' do
expect_no_offenses(<<~RUBY, 'foo.rb')
# cop will not read these contents
gem('rubocop')
gem('rubocop')
RUBY
end Can we put this: RSpec:
Language:
Expectations:
- expect_correction
- expect_no_offenses
- expect_offense into some additional YAML file so It looks like an immense effort to fix this all. With |
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.
Looks good, thanks!
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.
The cop itself looks fine. I'm worried about extending the Language though
@@ -61,9 +61,14 @@ RSpec: | |||
Pending: | |||
- pending | |||
Expectations: | |||
- are_expected |
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 change in Language potentially affects multiple cops (ExpectInHook, MultipleExpectations. StubbedMock). Perhaps it's worth mentioning it in the changelog. Also I'm not sure we should support the should expectations at all
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.
@bquorning what do you think about extending the default language?
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 haven’t personally used the ‘should’ syntax since RSpec 3 was released, but from the RSpec documentation it sounds like it’s not being removed, even in v4. So I guess we should support it?
@pirj I imagine you might know about official RSpec plans?
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.
All forms of should
will be removed from RSpec 4 with no replacement.
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.
Personally, I would not keep the burden of supporting should
, as it was soft-deprecated nine years ago and was disabled in the generated config since then:
For RSpec 3, we considered the idea of disabling the old syntax by default, forcing users to opt-in to use it.
But I still see people use it, even those who joined software development less than nine years ago 😄
it 'registers no offenses' do | ||
expect_no_offenses(<<~RUBY) | ||
RSpec.describe Foo do | ||
pending 'not implemented' |
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.
perhaps we should skip checking of pending or skipped examples in the first place.
In response to the review comments, I added the following changes later: - Prefer x_type? to is_a? - Use RSpec.Language.Examples - Add are_expected to expectation method names - Prefer on_block to on_send - Add more methods to RSpec.Language.Expectations - Use RSpec.Language.Expectations - Replace with clearer custom method names - Add some missing \@return comments
e1a1113
to
7a3a0a6
Compare
Thank you, @r7kamura ! |
This cop checks that each example has any expectation.
fixes #1319
Example
Background
Trying it out on my Rails project, I found the following bad cases by this Cop:
then I corrected the code like this:
Before submitting the PR make sure the following are checked:
master
(if not - rebase it).CHANGELOG.md
if the new code introduces user-observable changes.bundle exec rake
) passes (be sure to run this locally, since it may produce updated documentation that you will need to commit).If you have created a new cop:
config/default.yml
.Enabled: pending
inconfig/default.yml
.Enabled: true
in.rubocop.yml
.VersionAdded
indefault/config.yml
to the next minor version.If you have modified an existing cop's configuration options:
VersionChanged
inconfig/default.yml
to the next major version.