Make your RSpec tests better

Below is a (non-exhaustive) list of good practices that I developed when writing my RSpec tests.

1. Use context blocks a lot.  TIP: Write your context blocks first and then fill in the tests.  It helps re-use and organization.

GOOD:


context "campaign has locations" do
  context "when locations < 10" do
    ...
  end

  context "when locations >= 10" do
    ...
  end
end

BAD: (notice double context block, doesn’t promote code sharing because you need to setup the same scenario multiple times. Also if someone modifies the code, they will have to modify in multiple places)


context "campaign has locations" do
  context "when locations < 10" do
    ...
  end
end

context "campaign has locations" do
  context "when locations =< 10" do
    ...
  end
end

2. If you have too many context blocks, that MIGHT mean you need to refactor your method to smaller methods.

3. Make sure that cases belong to their proper context block:

BAD:


context "campaign has locations" do
  context "when locations < 10" do
    ...
  end
  context "when locations >= 10" do
    ...
  end
  context "when locations = 0" do #<--- BAD (should be outside context)
    ...
  end
end

4. Write unit tests for single methods first.  You can skip for small “trivial” methods and include tests for small methods in the calling methods.  Worry about integration last.

5. I usually write unit tests will full stubs to verify input and output.  I might throw in a few tests to test the interaction and method chain.

6. Make sure you DON’T writes tests that test other components. Assume dependent components are written correctly and stub them out.  Good example of this is for external APIs.

7. Make sure your test breaks if you make it false.  I can’t count how many times it hasn’t for myself.

8.  For loops, I usually write a test case to make sure everything happens correctly for 1 iteration.  Then I have a test case to test for n (usually between 2-5) iterations.  TIP: extract the entire contents of the loop into its own sub method.

9. In your before block, if you are testing a certain condition on an object.  Explicitly set that, and don’t rely on Factory defaults:

BAD:


context "when campaign budget is NULL" do
  before do
    @campaign = Factory :campaign   #factory sets campaign budget = nil
  end
end

GOOD:


context "when campaign budget is NULL" do
  before do
    @campaign = Factory :campaign, :budget => nil
  end
end
Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s