I tend to use before blocks to set instance variables. I then use those variables across my examples. I recently came upon let()
. According to RSpec docs, it is used to
... to define a memoized helper method. The value will be cached across multiple calls in the same example but not across examples.
How is this different from using instance variables in before blocks? And also when should you use let()
vs before()
?
let generates a method whose return value is memoized after the first call. This is known as lazy loading because the value is not loaded into memory until the method is called. Here is an example of how let is used within an RSpec test. let will generate a method called thing which returns a new instance of Thing .
I understood the difference between let and let! with a very simple example. Let me read the doc sentence first, then show the output hands on. ... let is lazy-evaluated: it is not evaluated until the first time the method it defines is invoked.
The let method should be called inside an example group. The first argument is the name of a variable to define. The let method is passed a block that computes the value of the variable, and the block will be called if the value of the variable is ever needed. In other words, let variables are lazily evaluated.
The it Keyword. The word it is another RSpec keyword which is used to define an “Example”. An example is basically a test or a test case. Again, like describe and context, it accepts both class name and string arguments and should be used with a block argument, designated with do/end.
I always prefer let
to an instance variable for a couple of reasons:
nil
, which can lead to subtle bugs and false positives. Since let
creates a method, you'll get a NameError
when you misspell it, which I find preferable. It makes it easier to refactor specs, too.before(:each)
hook will run before each example, even if the example doesn't use any of the instance variables defined in the hook. This isn't usually a big deal, but if the setup of the instance variable takes a long time, then you're wasting cycles. For the method defined by let
, the initialization code only runs if the example calls it.@
).let
and keeping my it
block nice and short.A related link can be found here: http://www.betterspecs.org/#let
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With