Skip to content

Commit

Permalink
Add new RSpec/EmptyHook cop
Browse files Browse the repository at this point in the history
Closes #811
  • Loading branch information
tejasbubane committed Apr 20, 2020
1 parent dff8957 commit 1f2d97c
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@
* Fix `RSpec/FilePath` detection when absolute path includes test subject. ([@eitoball][])
* Add new `Capybara/VisibilityMatcher` cop. ([@aried3r][])
* Ignore String constants by `RSpec/Describe`. ([@AlexWayfer][])
* Add new `RSpec/EmptyHook` cop. ([@tejasbubane][])

## 1.38.1 (2020-02-15)

Expand Down Expand Up @@ -496,3 +497,4 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
[@eitoball]: https://github.com/eitoball
[@aried3r]: https://github.com/aried3r
[@AlexWayfer]: https://github.com/AlexWayfer
[@tejasbubane]: https://github.com/tejasbubane
6 changes: 6 additions & 0 deletions config/default.yml
Expand Up @@ -105,6 +105,12 @@ RSpec/EmptyExampleGroup:
CustomIncludeMethods: []
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyExampleGroup

RSpec/EmptyHook:
Description: Checks for empty before and after hooks.
Enabled: true
VersionAdded: 1.38.2
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyHook

RSpec/EmptyLineAfterExample:
Description: Checks if there is an empty line after example blocks.
Enabled: true
Expand Down
41 changes: 41 additions & 0 deletions lib/rubocop/cop/rspec/empty_hook.rb
@@ -0,0 +1,41 @@
# frozen_string_literal: true

module RuboCop
module Cop
module RSpec
# Checks for empty before and after hooks.
#
# @example
# # bad
# before {}
# after do; end
# before(:all) do
# end
# all(:all) { nil }
#
# # good
# before { create_users }
# after do; cleanup_users; end
# before(:all) do
# create_feed
# end
# all(:all) { cleanup_feed }
class EmptyHook < Cop
MSG = 'Empty hook detected.'

def_node_matcher :empty_hook?, <<~PATTERN
(block
$(send nil? {:before :after}
(sym {:each :all :suite})?)
_ {(:nil) nil?})
PATTERN

def on_block(node)
empty_hook?(node) do |hook|
add_offense(hook)
end
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/rubocop/cop/rspec_cops.rb
Expand Up @@ -30,6 +30,7 @@
require_relative 'rspec/described_class_module_wrapping'
require_relative 'rspec/dialect'
require_relative 'rspec/empty_example_group'
require_relative 'rspec/empty_hook'
require_relative 'rspec/empty_line_after_example'
require_relative 'rspec/empty_line_after_example_group'
require_relative 'rspec/empty_line_after_final_let'
Expand Down
1 change: 1 addition & 0 deletions manual/cops.md
Expand Up @@ -29,6 +29,7 @@
* [RSpec/DescribedClassModuleWrapping](cops_rspec.md#rspecdescribedclassmodulewrapping)
* [RSpec/Dialect](cops_rspec.md#rspecdialect)
* [RSpec/EmptyExampleGroup](cops_rspec.md#rspecemptyexamplegroup)
* [RSpec/EmptyHook](cops_rspec.md#rspecemptyhook)
* [RSpec/EmptyLineAfterExample](cops_rspec.md#rspecemptylineafterexample)
* [RSpec/EmptyLineAfterExampleGroup](cops_rspec.md#rspecemptylineafterexamplegroup)
* [RSpec/EmptyLineAfterFinalLet](cops_rspec.md#rspecemptylineafterfinallet)
Expand Down
37 changes: 37 additions & 0 deletions manual/cops_rspec.md
Expand Up @@ -639,6 +639,43 @@ CustomIncludeMethods | `[]` | Array

* [https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyExampleGroup](https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyExampleGroup)

## RSpec/EmptyHook

Enabled by default | Supports autocorrection
--- | ---
Enabled | No

Checks for empty before and after hooks.

### Examples

```ruby
# bad
before {}
after do; end
before(:all) do
end
all(:all) { nil }

# good
before { create_users }
after do; cleanup_users; end
before(:all) do
create_feed
end
all(:all) { cleanup_feed }
```

### Configurable attributes

Name | Default value | Configurable values
--- | --- | ---
VersionAdded | `1.38.2` | String

### References

* [https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyHook](https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyHook)

## RSpec/EmptyLineAfterExample

Enabled by default | Supports autocorrection
Expand Down
76 changes: 76 additions & 0 deletions spec/rubocop/cop/rspec/empty_hook_spec.rb
@@ -0,0 +1,76 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::RSpec::EmptyHook do
subject(:cop) { described_class.new(config) }

let(:config) { RuboCop::Config.new }

shared_examples 'empty hook' do |hook_type|
it 'registers offense with empty block' do
expect_offense(<<~RUBY)
#{hook_type} {}
#{'^' * hook_type.length} Empty hook detected.
RUBY
end

it 'registers offense with empty single-line do-end' do
expect_offense(<<~RUBY)
#{hook_type} do; end
#{'^' * hook_type.length} Empty hook detected.
RUBY
end

it 'registers offense with empty multi-line do-end' do
expect_offense(<<~RUBY)
#{hook_type} do
#{'^' * hook_type.length} Empty hook detected.
end
RUBY
end

it 'registers offense with empty single-line nil' do
expect_offense(<<~RUBY)
#{hook_type} { nil }
#{'^' * hook_type.length} Empty hook detected.
RUBY
end

it 'registers offense with empty multi-line nil' do
expect_offense(<<~RUBY)
#{hook_type} do
#{'^' * hook_type.length} Empty hook detected.
nil
end
RUBY
end

it 'allows single-line non-empty blocks' do
expect_no_offenses(<<~RUBY)
#{hook_type} { create_users }
RUBY
end

it 'allows multi-line non-empty blocks' do
expect_no_offenses(<<~RUBY)
#{hook_type} do
create_users
create_businesses
end
RUBY
end
end

context 'with before hooks' do
it_behaves_like 'empty hook', 'before'
it_behaves_like 'empty hook', 'before(:each)'
it_behaves_like 'empty hook', 'before(:suite)'
it_behaves_like 'empty hook', 'before(:all)'
end

context 'with after hooks' do
it_behaves_like 'empty hook', 'after'
it_behaves_like 'empty hook', 'after(:each)'
it_behaves_like 'empty hook', 'after(:suite)'
it_behaves_like 'empty hook', 'after(:all)'
end
end

0 comments on commit 1f2d97c

Please sign in to comment.