Skip to content

Using let and given together

Jim Weirich edited this page May 24, 2013 · 1 revision

Given VS let

The Given in RSpec/Given is inspired by RSpec's let. In fact, it is nearly identical to let in implementation. Both define a lazy method that can be referenced later in the test.

So, if you have Given, why would you ever use let?

There is a difference in intention. Given says "Here is a named value that is needed for the setup of this specification." Whatever value is specified in the Given clause, that is part of the preconditions of spec.

Here's an example to highlight the difference: In the Semantic Expressions example, the :reduce method returns two items, a new expression and a (possibly) new environment.

describe "Statements" do
  describe Assign do
    Given(:five) { Number.new(5) }
    Given(:stmt) { Assign.new(:x, five) }
    describe "#reduce" do
      When(:result) { stmt.reduce({}) }
      Then { result == [DoNothing.new, {x: five}] }
    end
  end
end

The result returned by reduce is structured value. It's possible to assert equality on a structured result, but it is difficult to see the errors when they (inevitably) occur.

I like to break up the result from :reduce into parts, called :reduced_statement and :reduced_environment. I could create these named values with Given, but they aren't really part of the setup for the spec, they are just conveniently named values used in the assertions. Hence I will use let to specify them.

  describe Assign do
    Given(:five) { Number.new(5) }
    Given(:stmt) { Assign.new(:x, five) }
    describe "#reduce" do
      When(:result) { stmt.reduce({}) }
      let(:reduced_statement)   { result[0].inspect }
      let(:reduced_environment) { result[1] }

      Then { reduced_statement == "«do-nothing»" }
      Then { reduced_environment ==  {x: five} }
    end
  end

Summary

The key thing to remember is that if the named value is part of the setup for the specification, use Given to convey that meaning. If the named value is merely for convenience, then let is fine.


Return to Semantic Expression Examples