-
-
Notifications
You must be signed in to change notification settings - Fork 277
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #160 from nevir/feature/MultipleExpectations
Add `RSpec/MultipleExpectations` cop
- Loading branch information
Showing
7 changed files
with
192 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
require: rubocop-rspec | ||
|
||
inherit_from: .rubocop_todo.yml | ||
|
||
AllCops: | ||
DisplayCopNames: true | ||
TargetRubyVersion: 2.2 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# This configuration was generated by | ||
# `rubocop --auto-gen-config` | ||
# on 2016-08-05 22:48:55 -0700 using RuboCop version 0.42.0. | ||
# The point is for the user to remove these configuration records | ||
# one by one as the offenses are removed from the code base. | ||
# Note that changes in the inspected code, or installation of new | ||
# versions of RuboCop, may require this file to be generated again. | ||
|
||
# Offense count: 8 | ||
RSpec/MultipleExpectations: | ||
Max: 3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module RSpec | ||
# Checks if examples contain too many `expect` calls | ||
# | ||
# @see http://betterspecs.org/#single Single expectation test | ||
# | ||
# This cop is configurable using the `Max` option | ||
# and works with `--auto-gen-config`. | ||
# | ||
# @example | ||
# | ||
# # bad | ||
# describe UserCreator do | ||
# it 'builds a user' do | ||
# expect(user.name).to eq("John") | ||
# expect(user.age).to eq(22) | ||
# end | ||
# end | ||
# | ||
# # good | ||
# describe UserCreator do | ||
# it 'sets the users name' do | ||
# expect(user.name).to eq("John") | ||
# end | ||
# | ||
# it 'sets the users age' | ||
# expect(user.age).to eq(22) | ||
# end | ||
# end | ||
# | ||
# @example configuration | ||
# | ||
# # .rubocop.yml | ||
# RSpec/MultipleExpectations: | ||
# Max: 2 | ||
# | ||
# # not flagged by rubocop | ||
# describe UserCreator do | ||
# it 'builds a user' do | ||
# expect(user.name).to eq("John") | ||
# expect(user.age).to eq(22) | ||
# end | ||
# end | ||
# | ||
class MultipleExpectations < Cop | ||
include RuboCop::RSpec::Language, ConfigurableMax | ||
|
||
MSG = 'Too many expectations.'.freeze | ||
|
||
def_node_matcher :example?, <<-PATTERN | ||
(block (send _ {#{Examples::ALL.to_node_pattern}} ...) ...) | ||
PATTERN | ||
|
||
def_node_search :expect, '(send _ :expect ...)' | ||
|
||
def on_block(node) | ||
return unless example?(node) && (expectations = expect(node)) | ||
|
||
return if expectations.count <= max_expectations | ||
|
||
self.max = expectations.count | ||
|
||
flag_example(node, expectation_count: expectations.count) | ||
end | ||
|
||
private | ||
|
||
def flag_example(node, expectation_count:) | ||
method, = *node | ||
|
||
add_offense( | ||
method, | ||
:expression, | ||
MSG % { total: expectation_count, max: max_expectations } | ||
) | ||
end | ||
|
||
def max_expectations | ||
Integer(cop_config.fetch(parameter_name, 1)) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# frozen_string_literal: true | ||
|
||
describe RuboCop::Cop::RSpec::MultipleExpectations, :config do | ||
subject(:cop) { described_class.new(config) } | ||
|
||
context 'without configuration' do | ||
let(:cop_config) { Hash.new } | ||
|
||
it 'flags multiple expectations' do | ||
expect_violation(<<-RUBY) | ||
describe Foo do | ||
it 'uses expect twice' do | ||
^^^^^^^^^^^^^^^^^^^^^^ Too many expectations. | ||
expect(foo).to eq(bar) | ||
expect(baz).to eq(bar) | ||
end | ||
end | ||
RUBY | ||
end | ||
|
||
it 'approves of one expectation per example' do | ||
expect_no_violations(<<-RUBY) | ||
describe Foo do | ||
it 'does something neat' do | ||
expect(neat).to be(true) | ||
end | ||
it 'does something cool' do | ||
expect(cool).to be(true) | ||
end | ||
end | ||
RUBY | ||
end | ||
end | ||
|
||
context 'with configuration' do | ||
let(:cop_config) do | ||
{ 'Max' => '2' } | ||
end | ||
|
||
it 'permits two expectations' do | ||
expect_no_violations(<<-RUBY) | ||
describe Foo do | ||
it 'uses expect twice' do | ||
expect(foo).to eq(bar) | ||
expect(baz).to eq(bar) | ||
end | ||
end | ||
RUBY | ||
end | ||
|
||
it 'flags three expectations' do | ||
expect_violation(<<-RUBY) | ||
describe Foo do | ||
it 'uses expect three times' do | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Too many expectations. | ||
expect(foo).to eq(bar) | ||
expect(baz).to eq(bar) | ||
expect(qux).to eq(bar) | ||
end | ||
end | ||
RUBY | ||
end | ||
end | ||
|
||
it 'generates a todo based on the worst violation' do | ||
inspect_source(cop, <<-RUBY) | ||
describe Foo do | ||
it 'uses expect twice' do | ||
expect(foo).to eq(bar) | ||
expect(baz).to eq(bar) | ||
end | ||
it 'uses expect three times' do | ||
expect(foo).to eq(bar) | ||
expect(baz).to eq(bar) | ||
expect(qux).to eq(bar) | ||
end | ||
end | ||
RUBY | ||
|
||
expect(cop.config_to_allow_offenses).to eq('Max' => 3) | ||
end | ||
end |