Idiomatic shared state in RSpec
RSpec is an extremely convenient tool for structuring and writing specs, and I use it on all my ruby-projects.
One set of built-in helpers I’d like to cheer on a bit are let
and let!
, as they can greatly simplify setting up state for multiple examples. They exist to provide a simple and convenient way to create and share state between examples. When not using these methods, specs with a bit of shared state typically look like this:
This is easy to get started with, and when there are only a few variables in the before
block, things are fine. But if you have a typo in an example where you intended to use the @user
instance variable in an example, but you accidentally typed @usr
, you just get a nil
value, instead of a helpful error message regarding an unknown indentifier. This minor problem can be avoided by using let
instead, as you get an unknown indentifier error instead of a nil
value. Another issue is that all variables in the before
block are evaluated, whether or not they are actually used in the examples.
The excellent official RSpec 2 documentation has the following to say on let
, before showing clear examples of use:
let
andlet!
Use
let
to define a memoized helper method. The value will be cached across multiple calls in the same example but not across examples.Note that
let
is lazy-evaluated: it is not evaluated until the first time the method it defines is invoked. You can uselet!
to force the method’s invocation before each example.
The fact that results are both memoized and lazy-evaluated means no extra effort is expended if the value is not used in a given example. Performance win!
Use let
or let!
?
Please use the correct helper method - I’ve seen examples like this:
The exact same thing can be expressed directly and become more readable, just by adding a !
:
The let
and let!
helpers are available in from versions rspec 1.3.1
, and rspec-core 2.0.0
onwards. In a nutshell, this means they are available for use in Rails 2 and Rails 3 projects. Take them for a spin if you haven’t already, and tell me how it goes.
I recommend having a quick look at the Rspec 2.5 documentation now, as you’ll probably discover one or more neat new solutions to recurring issues when writing specs.
Hi, I'm Laust Rud Jacobsen, an experienced webapp developer specializing in Elixir, Ruby and PostgreSQL-based solutions. You can hire me to build awesome stuff for you. If you have any questions or comments, reach out at @laustrud or privately at work@valuestream.io.