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 29, 2020
1 parent 52a7fe1 commit 1968d08
Show file tree
Hide file tree
Showing 7 changed files with 296 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,7 @@
* Ignore String constants by `RSpec/Describe`. ([@AlexWayfer][])
* Drop support for ruby 2.3. ([@bquorning][])
* Fix multiple cops to detect `let` with proc argument. ([@tejasbubane][])
* Add new `RSpec/EmptyHook` cop. ([@tejasbubane][])

## 1.38.1 (2020-02-15)

Expand Down
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.39.0
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
40 changes: 40 additions & 0 deletions lib/rubocop/cop/rspec/empty_hook.rb
@@ -0,0 +1,40 @@
# 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
# after(:all) { }
#
# # good
# before { create_users }
# after do
# cleanup_users
# end
# before(:all) do
# create_feed
# end
# after(:all) { cleanup_feed }
class EmptyHook < Cop
MSG = 'Empty hook detected.'

def_node_matcher :empty_hook?, <<~PATTERN
(block $#{Hooks::ALL.send_pattern} _ 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
39 changes: 39 additions & 0 deletions manual/cops_rspec.md
Expand Up @@ -639,6 +639,45 @@ 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
after(:all) { }

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

### Configurable attributes

Name | Default value | Configurable values
--- | --- | ---
VersionAdded | `1.39.0` | 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
208 changes: 208 additions & 0 deletions spec/rubocop/cop/rspec/empty_hook_spec.rb
@@ -0,0 +1,208 @@
# frozen_string_literal: true

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

context 'with `before` hook' do
it 'detects offense for empty `before`' do
expect_offense(<<~RUBY)
before {}
^^^^^^ Empty hook detected.
RUBY
end

it 'detects offense for empty `before` with :each scope' do
expect_offense(<<~RUBY)
before(:each) {}
^^^^^^^^^^^^^ Empty hook detected.
RUBY
end

it 'detects offense for empty `before` with :example scope' do
expect_offense(<<~RUBY)
before(:example) {}
^^^^^^^^^^^^^^^^ Empty hook detected.
RUBY
end

it 'detects offense for empty `before` with :context scope' do
expect_offense(<<~RUBY)
before(:context) {}
^^^^^^^^^^^^^^^^ Empty hook detected.
RUBY
end

it 'detects offense for empty `before` with :all scope' do
expect_offense(<<~RUBY)
before(:all) {}
^^^^^^^^^^^^ Empty hook detected.
RUBY
end

it 'detects offense for empty `before` with :suite scope' do
expect_offense(<<~RUBY)
before(:suite) {}
^^^^^^^^^^^^^^ Empty hook detected.
RUBY
end

it 'accepts non-empty `before` hook' do
expect_no_offenses(<<~RUBY)
before { create_users }
RUBY
end

it 'accepts multiline `before` hook' do
expect_no_offenses(<<~RUBY)
before(:all) do
create_users
create_products
end
RUBY
end
end

context 'with `after` hook' do
it 'detects offense for empty `after`' do
expect_offense(<<~RUBY)
after {}
^^^^^ Empty hook detected.
RUBY
end

it 'accepts non-empty `after` hook' do
expect_no_offenses(<<~RUBY)
after { cleanup_users }
RUBY
end

it 'accepts multiline `after` hook' do
expect_no_offenses(<<~RUBY)
after(:suite) do
cleanup_users
cleanup_products
end
RUBY
end
end

context 'with `around` hook' do
it 'detects offense for empty `around`' do
expect_offense(<<~RUBY)
around {}
^^^^^^ Empty hook detected.
RUBY
end

it 'accepts non-empty `around` hook' do
expect_no_offenses(<<~RUBY)
around { yield }
RUBY
end

it 'accepts multiline `around` hook' do
expect_no_offenses(<<~RUBY)
around(:suite) do
setup_users
yield
end
RUBY
end
end

context 'with `prepend_before` hook' do
it 'detects offense for empty `prepend_before`' do
expect_offense(<<~RUBY)
prepend_before {}
^^^^^^^^^^^^^^ Empty hook detected.
RUBY
end

it 'accepts non-empty `prepend_before` hook' do
expect_no_offenses(<<~RUBY)
prepend_before { create_users }
RUBY
end

it 'accepts multiline `prepend_before` hook' do
expect_no_offenses(<<~RUBY)
prepend_before(:all) do
create_users
create_products
end
RUBY
end
end

context 'with `append_before` hook' do
it 'detects offense for empty `append_before`' do
expect_offense(<<~RUBY)
append_before {}
^^^^^^^^^^^^^ Empty hook detected.
RUBY
end

it 'accepts non-empty `append_before` hook' do
expect_no_offenses(<<~RUBY)
append_before { create_users }
RUBY
end

it 'accepts multiline `append_before` hook' do
expect_no_offenses(<<~RUBY)
append_before(:each) do
create_users
create_products
end
RUBY
end
end

context 'with `prepend_after` hook' do
it 'detects offense for empty `prepend_after`' do
expect_offense(<<~RUBY)
prepend_after {}
^^^^^^^^^^^^^ Empty hook detected.
RUBY
end

it 'accepts non-empty `prepend_after` hook' do
expect_no_offenses(<<~RUBY)
prepend_after { cleanup_users }
RUBY
end

it 'accepts multiline `prepend_after` hook' do
expect_no_offenses(<<~RUBY)
prepend_after(:all) do
cleanup_users
cleanup_products
end
RUBY
end
end

context 'with `append_after` hook' do
it 'detects offense for empty `append_after`' do
expect_offense(<<~RUBY)
append_after {}
^^^^^^^^^^^^ Empty hook detected.
RUBY
end

it 'accepts non-empty `append_after` hook' do
expect_no_offenses(<<~RUBY)
append_after { cleanup_users }
RUBY
end

it 'accepts multiline `append_after` hook' do
expect_no_offenses(<<~RUBY)
append_after(:all) do
cleanup_users
cleanup_products
end
RUBY
end
end
end

0 comments on commit 1968d08

Please sign in to comment.