Make your specs into stories

Damien Burke
4 min readJan 2, 2019

--

There are a lot of moving parts at Voom; riders, helicopters, and helipads interact in complex ways to ensure the effective operations. As a result, we often need a lot of setup when running our tests.

A large test setup can look like a random collection of unrelated facts. They are difficult to read, difficult to understand, and difficult to remember. Because humans are hard-wired to think in narrative, crafting test setup as stories makes them easier to read, easier to understand, and easier to remember.

Using stories, instead of mere collections of facts can make your specifications easier to read and understand.

An example set of facts

Individual one traveled from location one to location two at time zero. Individual one traveled from location two to location one at time one. Individual one traveled from location one to location three at time two. Individual one traveled from location three to location one at time three.

Without looking back at the example try to answer the following questions:

  • How many times did individual one arrive at location one?
  • Which location did individual one go to first - location three or location two?
  • Where did individual one end up?

Did you have to think a little bit to answer any of the questions? Were you unsure about the answer to any of the questions?

An example story

Adriana went to work at nine and came home at five. Then she went to a concert at seven and came home at eleven.

Our fictional Adriana arriving at work

It’s not exactly Hemingway, but notice how much easier and more enjoyable it is was to read.

Without looking back at the story, answer these questions:

  • How many times did Adriana go home?
  • Did Adriana go to the concert first or to work first?
  • Where did Adriana end up?

Did you get all of the questions right? Did the answers come to you easily and effortlessly?

RSpec facts

We can create a similar effect in RSpec. Here is a test setup that is a collection of facts:

let(:rider1) { FactoryBot.create(:rider) }let(:location1) { FactoryBot.create(:location) }
let(:location2) { FactoryBot.create(:location) }
let(:location3) { FactoryBot.create(:location) }
let!(:journey1) { FactoryBot.create(:journey, rider: rider1, origin: location1, destination: location2, time: Time.at(0)) }
let!(:journey2) { FactoryBot.create(:journey, rider: rider1, origin: location2, destination: location1, time: Time.at(1)) }
let!(:journey3) { FactoryBot.create(:journey, rider: rider1, origin: location1, destination: location3, time: Time.at(2)) }
let!(:journey4) { FactoryBot.create(:journey, rider: rider1, origin: location3, destination: location1, time: Time.at(3)) }

Can you tell if these expectations are correct without looking back at the setup?

specify { expect(location1.arrivals.count).to eq(2) }
specify ( expect(journey3).to be_later_than(journey1) }
specify { expect(rider1.current_location).to eq(location1) }

RSpec story

Here is an analogous setup that is crafted into a story.

let(:adriana) { FactoryBot.create(:rider) }let(:home) { FactoryBot.create(:location) }
let(:work) { FactoryBot.create(:location) }
let(:concert) { FactoryBot.create(:location) }
let!(:to_work) { FactoryBot.create(:journey, rider: adriana, origin: home, destination: work, time: Time.parse('9am')) }
let!(:from_work) { FactoryBot.create(:journey, rider: adriana, origin: work, destination: home, time: Time.parse('5pm')) }
let!(:to_concert) { FactoryBot.create(:journey, rider: adriana, origin: home, destination: concert, time: Time.parse('7pm')) }
let!(:from_concert) { FactoryBot.create(:journey, rider: adriana, origin: concert, destination: home, time: Time.parse('11pm')) }

Can you easily tell that these expectations are correct?

specify { expect(home.arrivals.count).to eq(2) }
specify ( expect(to_concert).to be_later_than(to_work) }
specify { expect(adriana.current_location).to eq(home) }

How this works

Stories are facts and occurrences fleshed out with characters, causality and emotional response. An indistinct person traveling from one indistinct location to another indistinct location is very different from Adriana returning home from the awesome concert she went to after a long day at work.

Our minds are hard wired to think in about these things (characters, causality, and emotions). By writing our specs to take advantage of this, we can enlist much more powerful and primal parts of our mind to help others understand what we have written.

Caveats

Don’t overdo it. Adding a lot of information in order to turn your test into a narrative will actually make the tests more complicated and more difficult to read. It doesn’t take a lot of information to create a narrative.

Don’t do this instead of making things simpler. A better solution to complicated test setup is to refactor the code. Often that means simplifying the business rules and domain model. Adding a more explicit narrative should be done in addition to that when it helps.

Conclusion

Sprinkling our specifications with narratives is one way we at Voom work to make our codebase clear, easy to read, easy to maintain, and enjoyable to work with. If that is something you enjoy, we are hiring.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Damien Burke
Damien Burke

Written by Damien Burke

Engineering leader with twenty years of experience in software startups

No responses yet

Write a response