RSpec
RSpec/AlignLeftLetBrace
RSpec/AlignRightLetBrace
RSpec/AnyInstance
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.4 |
- |
检查实例是否未被全局存根。
优先使用实例双重而不是存根类的任何实例
RSpec/AroundBlock
RSpec/Be
RSpec/BeEmpty
RSpec/BeEq
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
否 |
始终(不安全) |
2.9.0 |
2.16 |
检查可以使用be(…)
替换eq(…)
的期望。
be
匹配器通过身份进行比较,而eq
匹配器使用==
进行比较。布尔值和nil可以通过身份进行比较,因此be
匹配器更可取,因为它是一个更严格的测试。
RSpec/BeEql
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
否 |
始终(不安全) |
1.7 |
2.16 |
检查可以使用be(…)
替换eql(…)
的期望。
be
匹配器通过身份进行比较,而eql
匹配器使用eql?
进行比较。整数、浮点数、布尔值、符号和nil可以通过身份进行比较,因此be
匹配器更可取,因为它是一个更严格的测试。
此规则只检查 expect(…).to eql(…)
的实例。我们不检查 to_not
或 not_to
,因为 !eql?
比 !equal?
更严格。我们也不尝试标记 eq
,因为如果 a == b
且 b
可通过标识进行比较,则 a
不一定与 b
类型相同,因为 #==
运算符可以强制转换对象进行比较。
示例
# bad
expect(foo).to eql(1)
expect(foo).to eql(1.0)
expect(foo).to eql(true)
expect(foo).to eql(false)
expect(foo).to eql(:bar)
expect(foo).to eql(nil)
# good
expect(foo).to be(1)
expect(foo).to be(1.0)
expect(foo).to be(true)
expect(foo).to be(false)
expect(foo).to be(:bar)
expect(foo).to be(nil)
RSpec/BeNil
RSpec/BeforeAfterAll
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.12 |
2.23 |
检查是否使用 before/after(:all/:context)。
RSpec/ChangeByZero
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
2.11 |
2.14 |
优先使用否定匹配器而不是 to change.by(0)
。
在复合期望的情况下,规则建议使用 RSpec::Matchers#change
的否定匹配器。
默认情况下,规则不支持复合期望的自动更正,但如果您为 change
设置否定匹配器,例如使用 NegatedMatcher
选项设置 not_change
,则规则将执行自动更正。
示例
NegatedMatcher: ~(默认)
# bad
expect { run }.to change(Foo, :bar).by(0)
expect { run }.to change { Foo.bar }.by(0)
# bad - compound expectations (does not support autocorrection)
expect { run }
.to change(Foo, :bar).by(0)
.and change(Foo, :baz).by(0)
expect { run }
.to change { Foo.bar }.by(0)
.and change { Foo.baz }.by(0)
# good
expect { run }.not_to change(Foo, :bar)
expect { run }.not_to change { Foo.bar }
# good - compound expectations
define_negated_matcher :not_change, :change
expect { run }
.to not_change(Foo, :bar)
.and not_change(Foo, :baz)
expect { run }
.to not_change { Foo.bar }
.and not_change { Foo.baz }
NegatedMatcher: not_change
# bad (support autocorrection to good case)
expect { run }
.to change(Foo, :bar).by(0)
.and change(Foo, :baz).by(0)
expect { run }
.to change { Foo.bar }.by(0)
.and change { Foo.baz }.by(0)
# good
define_negated_matcher :not_change, :change
expect { run }
.to not_change(Foo, :bar)
.and not_change(Foo, :baz)
expect { run }
.to not_change { Foo.bar }
.and not_change { Foo.baz }
RSpec/ClassCheck
RSpec/ContainExactly
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
2.19 |
- |
检查contain_exactly
的使用情况。
此 cop 检查以下内容: - 匹配数组值时,优先使用match_array
。 - 使用contain_exactly
且没有参数时,优先使用be_empty
。
RSpec/ContextMethod
RSpec/ContextWording
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.20 |
2.13 |
检查context
文档字符串是否以允许的前缀开头。
默认的前缀列表是最小的。鼓励用户根据项目需求调整配置。其他可接受的前缀可能包括if
、unless
、for
、before
、after
或during
。如果需要,它们可以包含多个单词。
此 cop 可以使用AllowedPatterns
自定义允许的上下文描述模式。默认情况下,没有按模式进行检查。
RSpec/DescribeClass
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.0 |
2.7 |
检查顶级 describe 的第一个参数是否为常量。
它可以配置为在传递特定元数据时忽略字符串。
默认情况下忽略 Rails 和 Aruba 的 type
元数据。
示例
IgnoredMetadata
配置
# .rubocop.yml
# RSpec/DescribeClass:
# IgnoredMetadata:
# type:
# - request
# - controller
# bad
describe 'Do something' do
end
# good
describe TestedClass do
subject { described_class }
end
describe 'TestedClass::VERSION' do
subject { Object.const_get(self.class.description) }
end
describe "A feature example", type: :feature do
end
RSpec/DescribeMethod
RSpec/DescribedClass
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终(不安全) |
1.0 |
2.27 |
检查测试是否使用 described_class
。
如果 describe 的第一个参数是类,则该类将通过 described_class 公开给每个示例。
此 cop 可以使用 EnforcedStyle
、SkipBlocks
和 OnlyStaticConstants
选项进行配置。OnlyStaticConstants
仅在 EnforcedStyle
为 described_class
时才相关。
rspec-rails 的 controller
助手有一个已知的缺陷,它在不同的上下文中运行其块,并且 described_class
不可用。SkipBlocks
选项排除对所有非 RSpec 相关块的检测。
要将此设置缩小到仅特定目录,可以使用该目录本地覆盖的配置文件。
示例
EnforcedStyle: described_class
(默认)
# bad
describe MyClass do
subject { MyClass.do_something }
end
# good
describe MyClass do
subject { described_class.do_something }
end
RSpec/DescribedClassModuleWrapping
RSpec/Dialect
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
禁用 |
是 |
始终 |
1.33 |
- |
强制使用自定义 RSpec 方言。
方言可以基于以下 RSpec 方法
-
describe, context, feature, example_group
-
xdescribe, xcontext, xfeature
-
fdescribe, fcontext, ffeature
-
shared_examples, shared_examples_for, shared_context
-
it, specify, example, scenario, its
-
fit, fspecify, fexample, fscenario, focus
-
xit, xspecify, xexample, xscenario, skip
-
pending
-
prepend_before, before, append_before,
-
around
-
prepend_after, after, append_after
-
let, let!
-
subject, subject!
-
expect, is_expected, expect_any_instance_of
默认情况下,所有 RSpec 方法和别名都是允许的。通过设置类似的配置
RSpec/Dialect: PreferredMethods: context: describe
如果您之前使用过 RSpec/Capybara/FeatureMethods
规则,并且想要继续禁用所有具有相同原生 RSpec 方法的 Capybara 特定方法(例如,只是别名),请使用以下配置
RSpec/Dialect: PreferredMethods: background: :before scenario: :it xscenario: :xit given: :let given!: :let! feature: :describe
您可以预期以下行为
RSpec/EmptyExampleGroup
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
仅命令行(不安全) |
1.7 |
2.31 |
检查示例组是否不包含任何测试。
示例
用法
# bad
describe Bacon do
let(:bacon) { Bacon.new(chunkiness) }
let(:chunkiness) { false }
context 'extra chunky' do # flagged by rubocop
let(:chunkiness) { true }
end
it 'is chunky' do
expect(bacon.chunky?).to be_truthy
end
end
# good
describe Bacon do
let(:bacon) { Bacon.new(chunkiness) }
let(:chunkiness) { false }
it 'is chunky' do
expect(bacon.chunky?).to be_truthy
end
end
# good
describe Bacon do
pending 'will add tests later'
end
RSpec/EmptyHook
RSpec/EmptyLineAfterExample
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
1.36 |
- |
检查示例块后是否有空行。
RSpec/EmptyLineAfterExampleGroup
RSpec/EmptyLineAfterFinalLet
RSpec/EmptyLineAfterHook
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
1.27 |
2.13 |
检查钩子块后是否有空行。
AllowConsecutiveOneLiners
配置相邻的一行定义是否被视为违规。
示例
# bad
before { do_something }
it { does_something }
# bad
after { do_something }
it { does_something }
# bad
around { |test| test.run }
it { does_something }
# good
after { do_something }
it { does_something }
# fair - it's ok to have non-separated one-liners hooks
around { |test| test.run }
after { do_something }
it { does_something }
RSpec/EmptyLineAfterSubject
RSpec/EmptyOutput
RSpec/ExampleLength
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.5 |
2.3 |
检查过长的示例。
过长的示例通常难以理解。考虑提取一些行为,例如使用let
块或辅助方法。
您可以使用CountAsOne
设置要折叠的结构。可用的有:'array'、'hash'、'heredoc' 和 'method_call'。无论实际大小如何,每个结构都将被计为一行。
RSpec/ExampleWithoutDescription
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.22 |
- |
检查没有描述的示例。
RSpec 允许在没有提供描述或描述为空的情况下自动生成示例描述。使用specify
而不带描述是可以接受的。
此 cop 删除空描述。它还根据配置的样式定义是否允许自动生成的描述。
此规则可以使用 EnforcedStyle
选项进行配置
示例
# always good
specify do
result = service.call
expect(result).to be(true)
end
EnforcedStyle: always_allow
(默认)
# bad
it('') { is_expected.to be_good }
specify '' do
result = service.call
expect(result).to be(true)
end
# good
it { is_expected.to be_good }
specify do
result = service.call
expect(result).to be(true)
end
RSpec/ExampleWording
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
1.0 |
2.13 |
检查示例描述中的常见错误。
此 cop 将更正以 'should' 和 'it' 开头的文档字符串。此 cop 还将查找不足的示例并将其标记出来。
自动更正处于实验阶段 - 请谨慎使用!它可以使用 CustomTransform(例如,将 ⇒ 更改为 has)和 IgnoredWords(例如,仅)进行配置。
使用 DisallowedExamples 设置来防止不清楚或不足的描述。请注意,此配置将不区分大小写。
示例
# bad
it 'should find nothing' do
end
it 'will find nothing' do
end
# good
it 'finds nothing' do
end
# bad
it 'it does things' do
end
# good
it 'does things' do
end
RSpec/ExcessiveDocstringSpacing
RSpec/ExpectActual
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
1.7 |
2.23 |
检查包含字面值的 expect(…)
调用。
当预期值不是字面值时,会执行自动更正。
RSpec/ExpectChange
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终(不安全) |
1.22 |
2.5 |
检查更改匹配器的样式一致性。
强制使用将对象和属性作为参数传递给匹配器,或者传递一个读取属性值的块。
此 cop 可以使用 EnforcedStyle
选项进行配置。
示例
EnforcedStyle: method_call
(默认)
# bad
expect { run }.to change { Foo.bar }
expect { run }.to change { foo.baz }
# good
expect { run }.to change(Foo, :bar)
expect { run }.to change(foo, :baz)
# also good when there are arguments or chained method calls
expect { run }.to change { Foo.bar(:count) }
expect { run }.to change { user.reload.name }
RSpec/ExpectInHook
RSpec/ExpectInLet
RSpec/ExpectOutput
RSpec/Focus
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
仅命令行 |
1.5 |
2.31 |
检查示例是否被聚焦。
此代码检查器在某些情况下不支持自动更正。
示例
# bad
describe MyClass, focus: true do
end
describe MyClass, :focus do
end
fdescribe MyClass do
end
# good
describe MyClass do
end
# bad
fdescribe 'test' do; end
# good
describe 'test' do; end
# bad
fdescribe 'test' do; end
# good
describe 'test' do; end
# bad
shared_examples 'test', focus: true do; end
# good
shared_examples 'test' do; end
# bad
shared_context 'test', focus: true do; end
# good
shared_context 'test' do; end
# bad (does not support autocorrection)
focus 'test' do; end
RSpec/HookArgument
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
1.7 |
- |
检查传递给before
、around
和after
的参数。
此代码检查器检查为每个示例运行的 RSpec 钩子在指定时是否使用一致的风格。支持三种风格:"implicit"、"each" 和 "example"。所有风格的行为都相同。
RSpec/HooksBeforeExamples
RSpec/IdenticalEqualityAssertion
RSpec/ImplicitBlockExpectation
RSpec/ImplicitExpect
RSpec/ImplicitSubject
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
1.29 |
2.13 |
检查隐式主题(is_expected
/ should
)的使用。
此规则可以使用 EnforcedStyle
选项进行配置
示例
EnforcedStyle: single_line_only
(默认)
# bad
it do
is_expected.to be_truthy
end
# good
it { is_expected.to be_truthy }
it do
expect(subject).to be_truthy
end
EnforcedStyle: single_statement_only
# bad
it do
foo = 1
is_expected.to be_truthy
end
# good
it do
foo = 1
expect(subject).to be_truthy
end
it do
is_expected.to be_truthy
end
RSpec/IndexedLet
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
2.20 |
2.23 |
不要使用索引(例如,item_1
,item_2
)来设置测试数据。
这使得阅读测试变得更加困难,因为不清楚这个特定示例到底测试了什么。
可配置选项 AllowedIdentifiers
和 AllowedPatterns
也会读取 Naming/VariableNumber
中设置的那些选项。
示例
Max: 1
(默认)
# bad
let(:item_1) { create(:item) }
let(:item_2) { create(:item) }
let(:item1) { create(:item) }
let(:item2) { create(:item) }
# good
let(:visible_item) { create(:item, visible: true) }
let(:invisible_item) { create(:item, visible: false) }
Max: 2
# bad
let(:item_1) { create(:item) }
let(:item_2) { create(:item) }
let(:item_3) { create(:item) }
# good
let(:item_1) { create(:item) }
let(:item_2) { create(:item) }
RSpec/InstanceSpy
RSpec/InstanceVariable
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.0 |
1.7 |
检查规范中实例变量的使用。
此 cop 可以使用选项 AssignmentOnly
进行配置,该选项将配置 cop,仅当实例变量也在规范中被赋值时,才在实例变量使用上注册违规。
示例
# bad
describe MyClass do
before { @foo = [] }
it { expect(@foo).to be_empty }
end
# good
describe MyClass do
let(:foo) { [] }
it { expect(foo).to be_empty }
end
使用 AssignmentOnly 配置
# rubocop.yml
# RSpec/InstanceVariable:
# AssignmentOnly: true
# bad
describe MyClass do
before { @foo = [] }
it { expect(@foo).to be_empty }
end
# allowed
describe MyClass do
it { expect(@foo).to be_empty }
end
# good
describe MyClass do
let(:foo) { [] }
it { expect(foo).to be_empty }
end
RSpec/IsExpectedSpecify
RSpec/ItBehavesLike
RSpec/IteratedExpectation
RSpec/LeadingSubject
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
1.7 |
1.14 |
强制 subject 是测试中的第一个定义。
示例
# bad
let(:params) { blah }
subject { described_class.new(params) }
before { do_something }
subject { described_class.new(params) }
it { expect_something }
subject { described_class.new(params) }
it { expect_something_else }
# good
subject { described_class.new(params) }
let(:params) { blah }
# good
subject { described_class.new(params) }
before { do_something }
# good
subject { described_class.new(params) }
it { expect_something }
it { expect_something_else }
RSpec/LeakyConstantDeclaration
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.35 |
- |
检查是否没有声明类、模块或常量。
常量,包括类和模块,在块作用域中声明时,是在全局命名空间中定义的,并在示例之间泄漏。
如果多个示例可能定义一个 DummyClass
,而不是像在第一个示例中那样是一个空白类,后续示例将重新打开它并在不可预测的方式修改其行为。当代码库中存在的类被重新打开时,情况更糟。
匿名类是可以的,因为它们不会导致全局命名空间名称冲突。
示例
常量在示例之间泄漏
# bad
describe SomeClass do
OtherClass = Struct.new
CONSTANT_HERE = 'I leak into global namespace'
end
# good
describe SomeClass do
before do
stub_const('OtherClass', Struct.new)
stub_const('CONSTANT_HERE', 'I only exist during this example')
end
end
# bad
describe SomeClass do
class FooClass < described_class
def double_that
some_base_method * 2
end
end
it { expect(FooClass.new.double_that).to eq(4) }
end
# good - anonymous class, no constant needs to be defined
describe SomeClass do
let(:foo_class) do
Class.new(described_class) do
def double_that
some_base_method * 2
end
end
end
it { expect(foo_class.new.double_that).to eq(4) }
end
# good - constant is stubbed
describe SomeClass do
before do
foo_class = Class.new(described_class) do
def do_something
end
end
stub_const('FooClass', foo_class)
end
it { expect(FooClass.new.double_that).to eq(4) }
end
# bad
describe SomeClass do
module SomeModule
class SomeClass
def do_something
end
end
end
end
# good
describe SomeClass do
before do
foo_class = Class.new(described_class) do
def do_something
end
end
stub_const('SomeModule::SomeClass', foo_class)
end
end
RSpec/LetBeforeExamples
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
仅命令行 |
1.16 |
2.31 |
检查在示例之后出现的 let
定义。
示例
# bad
let(:foo) { bar }
it 'checks what foo does' do
expect(foo).to be
end
let(:some) { other }
it 'checks what some does' do
expect(some).to be
end
# good
let(:foo) { bar }
let(:some) { other }
it 'checks what foo does' do
expect(foo).to be
end
it 'checks what some does' do
expect(some).to be
end
RSpec/LetSetup
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.7 |
- |
检查用于测试设置的未引用 let!
调用。
RSpec/MatchArray
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
2.19 |
- |
检查 match_array
的使用位置。
此 cop 检查以下内容: - 使用值匹配数组时,优先使用 contain_exactly
。 - 使用空数组字面量时,优先使用 eq
和 match_array
。
RSpec/MessageChain
RSpec/MessageExpectation
RSpec/MessageSpies
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.9 |
- |
检查消息期望是否使用间谍设置。
此 cop 可以使用 EnforcedStyle
选项在您的配置中进行配置,并支持 --auto-gen-config
。
RSpec/MetadataStyle
RSpec/MissingExampleGroupArgument
RSpec/MissingExpectationTargetMethod
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
3.0 |
- |
检查是否使用了 .to
、not_to
或 to_not
。
RSpec::Expectations::ExpectationTarget 必须使用 to
、not_to
或 to_not
来运行。因此,此 cop 检查是否使用了其他方法。
RSpec/MultipleDescribes
RSpec/MultipleExpectations
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.7 |
1.21 |
检查示例是否包含太多expect
调用。
此 cop 可使用Max
选项配置,并与--auto-gen-config
一起使用。
示例
# 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' do
expect(user.age).to eq(22)
end
end
aggregate_failures: true
(默认)
# good - the cop ignores when RSpec aggregates failures
describe UserCreator do
it 'builds a user', :aggregate_failures do
expect(user.name).to eq("John")
expect(user.age).to eq(22)
end
end
aggregate_failures: false
# Detected as an offense
describe UserCreator do
it 'builds a user', aggregate_failures: false do
expect(user.name).to eq("John")
expect(user.age).to eq(22)
end
end
RSpec/MultipleMemoizedHelpers
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.43 |
- |
检查示例组是否包含太多let
和subject
调用。
此 cop 可使用Max
选项和AllowSubject
配置,该选项将配置 cop 以仅对let
的调用注册违规,而不对subject
的调用注册违规。
示例
# bad
describe MyClass do
let(:foo) { [] }
let(:bar) { [] }
let!(:baz) { [] }
let(:qux) { [] }
let(:quux) { [] }
let(:quuz) { {} }
end
describe MyClass do
let(:foo) { [] }
let(:bar) { [] }
let!(:baz) { [] }
context 'when stuff' do
let(:qux) { [] }
let(:quux) { [] }
let(:quuz) { {} }
end
end
# good
describe MyClass do
let(:bar) { [] }
let!(:baz) { [] }
let(:qux) { [] }
let(:quux) { [] }
let(:quuz) { {} }
end
describe MyClass do
context 'when stuff' do
let(:foo) { [] }
let(:bar) { [] }
let!(:booger) { [] }
end
context 'when other stuff' do
let(:qux) { [] }
let(:quux) { [] }
let(:quuz) { {} }
end
end
RSpec/MultipleSubjects
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
1.16 |
- |
检查示例组是否多次定义subject
。
此 cop 在某些情况下不支持自动更正。此 cop 的自动更正行为取决于重复类型的
-
如果定义了多个命名主题,则这可能表明覆盖的主题(除最后一个定义之外的所有主题)实际上用于定义帮助程序。在这种情况下,它们将被替换为
let
。 -
如果定义了多个未命名的主题,则这**只能**是死代码,我们将删除覆盖的主题定义。
-
如果使用
subject!
定义主题,我们将不会自动更正。这是一个边缘情况,人们可以自己将其移动到before
钩子中
示例
# bad
describe Foo do
subject(:user) { User.new }
subject(:post) { Post.new }
end
# good
describe Foo do
let(:user) { User.new }
subject(:post) { Post.new }
end
# bad (does not support autocorrection)
describe Foo do
subject!(:user) { User.new }
subject!(:post) { Post.new }
end
# good
describe Foo do
before do
User.new
Post.new
end
end
RSpec/NamedSubject
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.5.3 |
2.15 |
检查显式引用的测试主题。
RSpec 允许您使用subject { … }
声明“隐式主题”,这允许进行诸如it { is_expected.to be_valid }
之类的测试。如果您需要引用测试主题,您应该使用subject(:your_subject_name) { … }
显式命名它。您的测试主题应该是测试中最重要的对象,因此它们应该有一个描述性的名称。
此 cop 可在您的配置中使用EnforcedStyle
和IgnoreSharedExamples
配置,该配置不会报告共享示例组中隐式主题的违规。
示例
EnforcedStyle: always
(默认)
# bad
RSpec.describe User do
subject { described_class.new }
it 'is valid' do
expect(subject.valid?).to be(true)
end
end
# good
RSpec.describe User do
subject(:user) { described_class.new }
it 'is valid' do
expect(user.valid?).to be(true)
end
end
# also good
RSpec.describe User do
subject(:user) { described_class.new }
it { is_expected.to be_valid }
end
EnforcedStyle: named_only
# bad
RSpec.describe User do
subject(:user) { described_class.new }
it 'is valid' do
expect(subject.valid?).to be(true)
end
end
# good
RSpec.describe User do
subject(:user) { described_class.new }
it 'is valid' do
expect(user.valid?).to be(true)
end
end
# also good
RSpec.describe User do
subject { described_class.new }
it { is_expected.to be_valid }
end
# acceptable
RSpec.describe User do
subject { described_class.new }
it 'is valid' do
expect(subject.valid?).to be(true)
end
end
RSpec/NestedGroups
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.7 |
2.13 |
检查嵌套示例组。
此 cop 可使用 Max
选项配置,并支持 --auto-gen-config
。
示例
# bad
context 'when using some feature' do
let(:some) { :various }
let(:feature) { :setup }
context 'when user is signed in' do # flagged by rubocop
let(:user) do
UserCreate.call(user_attributes)
end
let(:user_attributes) do
{
name: 'John',
age: 22,
role: role
}
end
context 'when user is an admin' do # flagged by rubocop
let(:role) { 'admin' }
it 'blah blah'
it 'yada yada'
end
end
end
# good
context 'using some feature as an admin' do
let(:some) { :various }
let(:feature) { :setup }
let(:user) do
UserCreate.call(
name: 'John',
age: 22,
role: 'admin'
)
end
it 'blah blah'
it 'yada yada'
end
Max: 3
(默认)
# bad
describe Foo do
context 'foo' do
context 'bar' do
context 'baz' do # flagged by rubocop
end
end
end
end
Max: 2
# bad
describe Foo do
context 'foo' do
context 'bar' do # flagged by rubocop
context 'baz' do # flagged by rubocop
end
end
end
end
RSpec/NoExpectationExample
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
否 |
否 |
2.13 |
2.14 |
检查示例是否包含任何期望。
默认情况下,所有 RSpec 的示例和期望方法都包含在内。如果您使用的是自己的自定义方法,请添加以下配置
RSpec: Language: Examples: Regular: - custom_it Expectations: - custom_expect
此 cop 可以使用 AllowedPatterns
选项自定义允许的期望方法模式。默认情况下允许 ^expect_
和 ^assert_
。
RSpec/NotToNot
RSpec/OverwritingSetup
RSpec/Pending
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
禁用 |
是 |
否 |
1.25 |
- |
检查任何挂起的或跳过的示例。
RSpec/PendingWithoutReason
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
2.16 |
- |
检查没有原因的挂起或跳过示例。
示例
# bad
pending 'does something' do
end
# bad
it 'does something', :pending do
end
# bad
it 'does something' do
pending
end
# bad
xdescribe 'something' do
end
# bad
skip 'does something' do
end
# bad
it 'does something', :skip do
end
# bad
it 'does something' do
skip
end
# bad
it 'does something'
# good
it 'does something' do
pending 'reason'
end
# good
it 'does something' do
skip 'reason'
end
# good
it 'does something', pending: 'reason' do
end
# good
it 'does something', skip: 'reason' do
end
RSpec/PredicateMatcher
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终(不安全) |
1.16 |
- |
优先使用谓词匹配器而不是直接使用谓词方法。
RSpec 为谓词方法定义了魔法匹配器。此 cop 建议使用谓词匹配器,而不是直接使用谓词方法。
示例
Strict: true, EnforcedStyle: inflected(默认)
# bad
expect(foo.something?).to be_truthy
# good
expect(foo).to be_something
# also good - It checks "true" strictly.
expect(foo.something?).to be(true)
Strict: false, EnforcedStyle: inflected
# bad
expect(foo.something?).to be_truthy
expect(foo.something?).to be(true)
# good
expect(foo).to be_something
RSpec/ReceiveCounts
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
1.26 |
- |
检查 once
和 twice
接收计数匹配器的使用情况。
示例
# bad
expect(foo).to receive(:bar).exactly(1).times
expect(foo).to receive(:bar).exactly(2).times
expect(foo).to receive(:bar).at_least(1).times
expect(foo).to receive(:bar).at_least(2).times
expect(foo).to receive(:bar).at_most(1).times
expect(foo).to receive(:bar).at_most(2).times
# good
expect(foo).to receive(:bar).once
expect(foo).to receive(:bar).twice
expect(foo).to receive(:bar).at_least(:once)
expect(foo).to receive(:bar).at_least(:twice)
expect(foo).to receive(:bar).at_most(:once)
expect(foo).to receive(:bar).at_most(:twice).times
RSpec/ReceiveMessages
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终(不安全) |
2.23 |
- |
检查在同一个对象上存根的多个消息。
示例
# bad
before do
allow(Service).to receive(:foo).and_return(bar)
allow(Service).to receive(:baz).and_return(qux)
end
# good
before do
allow(Service).to receive_messages(foo: bar, baz: qux)
end
# good - ignore same message
before do
allow(Service).to receive(:foo).and_return(bar)
allow(Service).to receive(:foo).and_return(qux)
end
RSpec/ReceiveNever
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
1.28 |
- |
优先使用 not_to receive(…)
而不是 receive(…).never
。
RSpec/RedundantPredicateMatcher
RSpec/RemoveConst
RSpec/RepeatedDescription
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.9 |
- |
检查示例组中重复的描述字符串。
示例
# bad
RSpec.describe User do
it 'is valid' do
# ...
end
it 'is valid' do
# ...
end
end
# good
RSpec.describe User do
it 'is valid when first and last name are present' do
# ...
end
it 'is valid when last name only is present' do
# ...
end
end
# good
RSpec.describe User do
it 'is valid' do
# ...
end
it 'is valid', :flag do
# ...
end
end
RSpec/RepeatedExample
RSpec/RepeatedExampleGroupBody
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.38 |
- |
检查重复的 describe 和 context 块体。
示例
# bad
describe 'cool feature x' do
it { cool_predicate }
end
describe 'cool feature y' do
it { cool_predicate }
end
# good
describe 'cool feature' do
it { cool_predicate }
end
describe 'another cool feature' do
it { another_predicate }
end
# good
context 'when case x', :tag do
it { cool_predicate }
end
context 'when case y' do
it { cool_predicate }
end
# good
context Array do
it { is_expected.to respond_to :each }
end
context Hash do
it { is_expected.to respond_to :each }
end
RSpec/RepeatedExampleGroupDescription
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.38 |
- |
检查重复的示例组描述。
示例
# bad
describe 'cool feature' do
# example group
end
describe 'cool feature' do
# example group
end
# bad
context 'when case x' do
# example group
end
describe 'when case x' do
# example group
end
# good
describe 'cool feature' do
# example group
end
describe 'another cool feature' do
# example group
end
# good
context 'when case x' do
# example group
end
context 'when another case' do
# example group
end
RSpec/RepeatedIncludeExample
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.44 |
- |
检查重复包含的共享示例。
示例
# bad
describe 'foo' do
include_examples 'cool stuff'
include_examples 'cool stuff'
end
# bad
describe 'foo' do
it_behaves_like 'a cool', 'thing'
it_behaves_like 'a cool', 'thing'
end
# bad
context 'foo' do
it_should_behave_like 'a duck'
it_should_behave_like 'a duck'
end
# good
describe 'foo' do
include_examples 'cool stuff'
end
describe 'bar' do
include_examples 'cool stuff'
end
# good
describe 'foo' do
it_behaves_like 'a cool', 'thing'
it_behaves_like 'a cool', 'person'
end
# good
context 'foo' do
it_should_behave_like 'a duck'
it_should_behave_like 'a goose'
end
RSpec/RepeatedSubjectCall
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
2.27 |
- |
检查对 subject 的重复调用,缺少对 subject 的记忆。
示例
# bad
it do
subject
expect { subject }.to not_change { A.count }
end
it do
expect { subject }.to change { A.count }
expect { subject }.to not_change { A.count }
end
# good
it do
expect { my_method }.to change { A.count }
expect { my_method }.to not_change { A.count }
end
# also good
it do
expect { subject.a }.to change { A.count }
expect { subject.b }.to not_change { A.count }
end
RSpec/ReturnFromStub
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
1.16 |
1.22 |
检查存根返回值设置的风格一致性。
在返回值为常量的情况下,强制使用 and_return
或块式返回。忽略动态返回值,因为结果会不同。
此规则可以使用 EnforcedStyle
选项进行配置
示例
RSpec/ScatteredLet
RSpec/ScatteredSetup
RSpec/SharedContext
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
1.13 |
- |
检查 shared_context
和 shared_examples
的正确使用。
如果没有定义示例,请使用 shared_context
。如果没有定义 setup,请使用 shared_examples
。
示例
# bad
RSpec.shared_context 'only examples here' do
it 'does x' do
end
it 'does y' do
end
end
# good
RSpec.shared_examples 'only examples here' do
it 'does x' do
end
it 'does y' do
end
end
# bad
RSpec.shared_examples 'only setup here' do
subject(:foo) { :bar }
let(:baz) { :bazz }
before do
something
end
end
# good
RSpec.shared_context 'only setup here' do
subject(:foo) { :bar }
let(:baz) { :bazz }
before do
something
end
end
RSpec/SharedExamples
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
1.25 |
2.26 |
检查共享示例名称的风格一致性。
强制使用 string
或 symbol
作为共享示例名称。
此规则可以使用 EnforcedStyle
选项进行配置
示例
EnforcedStyle: string
(默认)
# bad
it_behaves_like :foo_bar_baz
it_should_behave_like :foo_bar_baz
shared_examples :foo_bar_baz
shared_examples_for :foo_bar_baz
include_examples :foo_bar_baz
# good
it_behaves_like 'foo bar baz'
it_should_behave_like 'foo bar baz'
shared_examples 'foo bar baz'
shared_examples_for 'foo bar baz'
include_examples 'foo bar baz'
EnforcedStyle: symbol
# bad
it_behaves_like 'foo bar baz'
it_should_behave_like 'foo bar baz'
shared_examples 'foo bar baz'
shared_examples_for 'foo bar baz'
include_examples 'foo bar baz'
# good
it_behaves_like :foo_bar_baz
it_should_behave_like :foo_bar_baz
shared_examples :foo_bar_baz
shared_examples_for :foo_bar_baz
include_examples :foo_bar_baz
RSpec/SingleArgumentMessageChain
RSpec/SkipBlockInsideExample
RSpec/SortMetadata
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终 |
2.14 |
- |
按字母顺序对 RSpec 元数据进行排序。
RSpec/SpecFilePathFormat
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
2.24 |
- |
检查规范文件路径是否一致且格式良好。
示例
# bad
whatever_spec.rb # describe MyClass
my_class_spec.rb # describe MyClass, '#method'
# good
my_class_spec.rb # describe MyClass
my_class_method_spec.rb # describe MyClass, '#method'
my_class/method_spec.rb # describe MyClass, '#method'
RSpec/SpecFilePathSuffix
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
2.24 |
- |
检查规范文件路径后缀是否一致且格式良好。
RSpec/StubbedMock
RSpec/SubjectDeclaration
RSpec/SubjectStub
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.7 |
2.8 |
检查存根测试主题。
当主题也在父示例组中定义时,检查嵌套主题存根以获取最内层主题定义。
示例
# bad
describe Article do
subject(:article) { Article.new }
it 'indicates that the author is unknown' do
allow(article).to receive(:author).and_return(nil)
expect(article.description).to include('by an unknown author')
end
end
# bad
describe Article do
subject(:foo) { Article.new }
context 'nested subject' do
subject(:article) { Article.new }
it 'indicates that the author is unknown' do
allow(article).to receive(:author).and_return(nil)
expect(article.description).to include('by an unknown author')
end
end
end
# good
describe Article do
subject(:article) { Article.new(author: nil) }
it 'indicates that the author is unknown' do
expect(article.description).to include('by an unknown author')
end
end
RSpec/UndescriptiveLiteralsDescription
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
2.29 |
- |
描述应该具有描述性。
如果示例组或示例仅包含execute string
、数字和正则表达式,则描述不清楚。
RSpec/UnspecifiedException
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.30 |
- |
检查检查引发的错误中是否指定了错误。
强制使用异常类型、字符串或正则表达式之一来匹配异常消息,作为raise_error
的参数。
示例
# bad
expect {
raise StandardError.new('error')
}.to raise_error
# good
expect {
raise StandardError.new('error')
}.to raise_error(StandardError)
expect {
raise StandardError.new('error')
}.to raise_error('error')
expect {
raise StandardError.new('error')
}.to raise_error(/err/)
expect { do_something }.not_to raise_error
RSpec/VariableDefinition
RSpec/VariableName
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
否 |
1.40 |
2.13 |
检查记忆的帮助器名称是否使用配置的样式。
可以使用AllowedPatterns
选项将变量排除在检查之外。
示例
EnforcedStyle: snake_case(默认)
# bad
subject(:userName1) { 'Adam' }
let(:userName2) { 'Adam' }
# good
subject(:user_name_1) { 'Adam' }
let(:user_name_2) { 'Adam' }
RSpec/VerifiedDoubleReference
默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
---|---|---|---|---|
已启用 |
是 |
始终(不安全) |
2.10.0 |
2.12 |
检查一致的已验证双重引用样式。
仅调查属于支持样式之一的引用。
此 cop 可以使用 EnforcedStyle
选项在您的配置中进行配置,并支持 --auto-gen-config
。
示例
EnforcedStyle: constant
(默认)
# bad
let(:foo) do
instance_double('ClassName', method_name: 'returned_value')
end
# good
let(:foo) do
instance_double(ClassName, method_name: 'returned_value')
end