describe
blocks to wrap a set of tests against one functionality, such as tests for a single method.context
blocks to wrap a set of tests against one functionality in the same state.it
blocks, each with one expect
:
describe '#my_cool_method' do context 'when foo is bar' do before { subject.foo = 'bar' } it 'returns true' do expect(subject.my_cool_method).to eq(true) end it 'increases count of thing' do expect { subject.my_cool_method }.to change(Thing, :count).by(1) end end context 'when foo is not bar' do before { subject.foo = 'other value' } it 'returns false' do expect(subject.my_cool_method).to eq(false) end it 'does not change count of thing' do expect { subject.my_cool_method }.to_not change(Thing, :count) end end end
context
block.# BAD it 'should eat the bear' do
# GOOD it 'eats the bear' do
subject
:
# BAD it 'includes location' do expect(assigns('message')).to match(/it was born in Belville/) end it 'sets creator' do expect(assigns('message').creator).to match(/Topolino/) end
# GOOD describe '@message' do subject { assigns('message') } it 'includes location' do expect(subject).to match(/it was born in Belville/) end it 'sets creator' do expect(subject.creator).to match(/Topolino/) end end
let(:variable)
/let!(:variable)
instead of before { @variable = ... }
.
let
when you only need the variable initialized when it is first referenced.let!
when you need the variable initialized when the containing block is initialized. Example: to create records before testing an #index Rails action that lists records.it
, describe
, and context
blocks.let
, before
, and after
blocks before it
blocks.let
, before
, after
, and subject
blocks.let
/before
/after
/subject
and it
blocks:
# BAD before { Foo.bar = true } after { Foo.bar = false } it 'does something' do ... end it 'does something else' do ... end let(:var) { create(:var) } subject { var.fiddly_bits }
# GOOD before { Foo.bar = true } let(:var) { create(:var) } after { Foo.bar = false } subject { var.fiddly_bits } it 'does something' do ... end it 'does something else' do ... end
{
}
when the let
/before
/after
/subject
definition will fit within 80 characters. Otherwise, use multi-line blocks with do
end
.it
block has a description or goes over 80 characters, use do
end
on multiple lines. Otherwise, use {
}
:
# BAD it 'returns true' { expect(subject.foo).to eq(true) } it do is_expected.to respond_with(200) end
# GOOD it 'returns true' do expect(subject.foo).to eq(true) end it { is_expected.to respond_with(200) }
# BAD it { is_expected.to respond_with 200 } it { is_expected.to(respond_with 200) } it { is_expected.to(respond_with(200)) }
# GOOD it { is_expected.to respond_with(200) }