In general, we try to adhere to the BetterSpecs guidelines. This document is a few extensions and key points from that.
- Make liberal use of
describeandcontextblocks - Only use the
expectandis_expected.tosyntax - Create only the data you need
- In unit tests, avoid touching the database, objects should be built in memory
- Never mock the object under test, only objects which it talks to
- Use shared examples carefully and only where it makes sense. Duplication is far cheaper than the wrong abstraction
-
letblocks should use multiple line{ }proc syntax.{ }syntax is less distracting thando end[link]# Bad let(:foo) do some_very_long_instantiation end # Good let(:bar) { some_very_long_instantiation } # Also good let(:baz) { 'baz' }
-
Use
{ }blocks for expectations [link]# bad expect do something end.to change(Something, :else) # good expect { something }.to change(Something, :else) # also good expect { something }.to change(Something, :else)
-
Use
do endforbeforeblocks [link]# bad before { do_something } # ok before { do_something } # good before do do_something end
The difference between
beforeandlet/expectis due to how it reads. e.glet(:foo) { :bar }reads like 'let foo be equal to bar' whereasbefore do something; endreads like 'before the test, do this thing'. -
Extract hardcoded values to well-named
letblocks, in the same manner as constants [link]# bad expect(1 + 2).to eq(3) # good subject { 1 + 2 } let(:expected_result) { 3 } it { is_expected.to eq(expected_result)}