I just started writing RSpec tests, and I came across thoughtbot's Style Guide, which recommends against let
, let!
, before
and subject
(among others).
I've also read similar suggestions in a few other places (including the old RSpec docs warning about before(:all)
), but I can't seem to find the actual argument against them.
So the question is:
Why shouldn't I be using those methods in my tests? What is the better approach?
Summary: RSpec's subject is a special variable that refers to the object being tested. Expectations can be set on it implicitly, which supports one-line examples. It is clear to the reader in some idiomatic cases, but is otherwise hard to understand and should be avoided.
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 .
Don't use should Do not use should when describing your tests. Use the third person in the present tense. Even better start using the new expectation syntax. See the should_not gem for a way to enforce this in RSpec and the should_clean gem for a way to clean up existing RSpec examples that begin with 'should.
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.
Interesting question; something that I want to know more about as well.... So dug in a bit, and here is what I uncovered:
let
, etc.In an earlier version of the style guide, there's more to that statement:
Avoid its, let, let!, specify, subject, and other DSLs. Prefer explicitness and consistency.
ThoughtBot folks made a post on let name let's not. See also the link to the Github Commit Comment conversation
On one of their recent podcasts Joe Ferris, the CTO of ThoughtBot, explains why it's not a good idea to use let
and subject
. Check out the podcast titled Something Else Was Smellier from the 27m37s mark onwards for the next 5 minutes.
Testing Anti-pattern 'Mystery Guest' which is dealt with in detail in an older ThoughtBot blogpost is the main reason for why not to use let
and its cousins.
To summarize my understanding of all the above very succinctly:
Using
let
et al makes it difficult to understand what's happening within the test on a quick glance, and requires the person to spend some time in making the connections.Write tests such that it is easy to understand without much effort.
In addition, using
let
liberally in tests results in over-sharing among the tests, as well as makes implicitcommon fixtures
- i.e. having a common fixture to start with for every test being written even when it does not apply.
The argument against using before(:all)
is straight-forward. As explained in the old rspec documentation:
Warning: The use of before(:all) and after(:all) is generally discouraged because it introduces dependencies between the Examples. Still, it might prove useful for very expensive operations if you know what you are doing.
before(:all) gets executed only once at the start of the ExampleGroup. As such there is a potential to inadvertently introduce dependencies between the Examples. Thoughtbot's assertion about the tests not being easy to understand applies to this as well.
In conclusion, the advise for writing better specs seems to be:
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