Skip to content

default lets to a uuid if no block given

Created by: markjlorenz

This patch encourages correct specs by discouraging "magic strings".

A common pattern I see in specs is:

let(:username)    { "teh user" }
let(:email)       { "an-email@example.com" }
let(:password)    { "sekret" }
let(:description) { "our favorite user" }

Basically, the spec author is just filling in junk values to populate a record. These junk values tend to become "magic strings" in the test:

expect(user.email).to eq("an-email@example.com")

It's also unclear to the next developer reading the spec if there really is something special about the values in the let, or if they are just junk values.

Both of these problems can be solved by using UUIDs anywhere you'd use a junk value:

let(:email) { SecureRandom.uuid }

This has the added benefit of preventing a whole class of specification errors: false positives caused by misunderstanding the state of the system.

In a test with a shared resource, like a database, those magic values may already exist in the database, making the example expect above susceptible to false positives.

When using UUIDs for all junk values, you can be reasonable certain that each let is globally unique, even in a shared resource. This also allows them to be treated as quasi-primary keys:

expect(User.find_by_description(description)).to be_present

Finally, it's really nice not having to think up the junk values. Naming things is hard, even if you don't care about the name.


A consequence of the UUID technique is that you end up with lots of lets like:

let(:username)    { SecureRandom.uuid }
let(:email)       { SecureRandom.uuid }
let(:password)    { SecureRandom.uuid }
let(:description) { SecureRandom.uuid }

With this patch, this can be written as:

let(:username)
let(:email)
let(:password)
let(:description)

The examples I used here are slated towards a Rails application, but this technique is useful anytime you don't care about the value of the let, which is almost always in my experience.

I realize I'm asking for a significant change to rspec's behavior. If I've been unclear in this pull request, please ask for clarification.

Merge request reports