Anyone can write a decent test description. But by paying attention to this little detail you can write great test descriptions:

Block descriptions should start with a word that forms a readable sentence in conjunction with the block function name.

That’s it! It doesn’t matter if you’re using JavaScript, Ruby or any other language. Test descriptions that can be read as plain English are better than test descriptions that cannot.

But what does this really mean in practice? Let’s find out.

describe

describe defines the subject under test:

describe 'Watch' do
  # ...
end

Here we are testing the Watch class.

describe should be followed by the class, function or object that we want to test.

it

it lays out the test case — the behaviour and outcome we expect. But linguistically, it refers to the actual thing we are testing:

describe 'Watch' do
  it 'should tell the time' do
    # ...
  end
end

We are meant to read the test description as if it were a sentence.

It should tell the time.

or

The watch should tell the time.

That is why it should be followed by the words “should” or “must”.

An alternative is to write test descriptions in the present tense:

describe 'Watch' do
  it 'tells the time' do
    # ...
  end
end

This still works as a sentence:

It tells the time.

or

The watch tells the time.

context

context groups tests that are made under the same circumstances:

describe 'Watch' do
  context 'when under water' do
    before do
      placeWatchUnderWater() # setup common to all tests inside this context
    end

    it 'should still tell the time' do # it's a diver's watch!
      # ...
    end

    it 'should measure depth' do
      # ...
    end
  end
end

Once again we are meant to read the test description as if it were a sentence.

When under water, it should still tell the time.

or

The watch, when under water, should still tell the time.

That is why context should be followed by the words “when”, “with”, “without” or “if”.

By adopting this simple guideline you can make your test descriptions easier to read and comprehend.


An added bonus is that many testing frameworks can be configured to output their results in a BDD format.

For example, using rspec’s format option, when all the tests pass:

$ rspec -fd watch.rb
Watch
  should tell the time
  when under water
    should still tell the time
    should measure depth

Finished in 0.00237 seconds
3 examples, 0 failures

And when some tests fail:

$ rspec -fd watch.rb
Watch
  should tell the time
  when under water
    should still tell the time (FAILED - 1)
    should measure depth (FAILED - 2)

Failures:

  1) Watch when under water should still tell the time
     Failure/Error: expect(watch.time).to eq '12:00'

       expected: "12:00"
            got: "0"

       (compared using ==)

  2) Watch when under water should measure depth
     Failure/Error: expect(watch.depth).to eq 10

       expected: 10
            got: 0

       (compared using ==)

Finished in 0.02115 seconds
3 examples, 2 failures

Failed examples:

rspec ./watch.rb:22 # Watch when under water should still tell the time
rspec ./watch.rb:26 # Watch when under water should measure depth

Notice how the test descriptions can be read as full sentences. We can immediately tell what went wrong.

It’s not a diver’s watch after all!