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) }