Two weeks ago I started this series with this post. I got a little side tracked last week and earlier this week due to receiving my first job offer in tech, but I’m trying to get back on track by writing this. This post is the second installment of this RSpec series and we will be covering a few really common Rspec helper methods and hooks: let
, before
, and after
.
Before you start thinking “but what about include
, match
, raise_error
, etc”, don’t you worry. I will be covering these expectations and matchers in the next installment of this series. I thought they deserved their own post as there are quite a few that I plan on covering. With that said, let’s go ahead and dive into these RSpec helper methods and hooks.
after
I’m going to do this a little backwards and talk about after
first here. It’s a relatively easy concept to grasp, which is why I’m starting here and then working our way into the more complex ones.
after
accepts an argument of all
or each
and executes whatever functionality you give it either after each test has completed or after all the tests have executed.
Take a moment and consider what order you think these would print out in before looking below this line!
Were you right?! If you were, YAY! If not, just take a moment and re-read the description above. Pay special attention to the italicized words and the words passed as arguments to each after
statement.
let
and before
In this section we are going to discuss the helper method let
and the hook before
. before
is similar to after
, as it can also accept the arguments all
and each
. The difference is that this hook type is excited either before all tests are executed or before each test is executed.
Again, let's see if you can guess the correct order of output!
Now that we have that comparison out of the way I want to discuss some difficulties I had while learning to build RSpec tests. When I began writing tests, I hit a snag and I couldn’t figure out what was happening. It took me a while to realize that I was using the hook before
instead of the helper method let
. The big difference between these two is that let
queries the database one time and saves the newly created object as a local variable, meanwhile using before
to create a database query queries the database at the beginning of each test, which increases load time and slows down your tests.
What I was doing wrong was that I was writing my tests expecting an attribute of the user
to equal something specific, but I hadn’t included a before
statement in that specific test, nor was I using before(:each)
or before(:all)
. I kept receiving an error saying that the user
did not exist. Can you guess why this is from what I’ve told you so far?
You are right if you’re thinking that before
doesn’t save the object to a local variable, so it really didn’t exist within the test I was working on. It had only existed as an instance variable in the test I had used it previously. So, where it was applicable, I removed all the before
methods and used let
in its place, that way I only had to query my database one time and had a ready to use local variable for multiple tests.
Outside of the amount of times you query the database there is one more snag to using before
. When a developer uses before
, this database query has to be saved as an instance variable. At first this doesn’t seem to be problematic, but it could be. The reason for this is because in tests, instance variables “spring into existence” as nil if they weren’t previously defined. This means that if you have a typo in your variable, your code could possibly still work properly.
Let’s take a situation where you may be testing to see if a user is logged out. You’d expect the test to check if the user is logged out by testing if @user
is equal to nil
. If you accidentally typed @usr
your test would still pass because @usr
does equal nil
, meanwhile you have no idea if @user
is actually nil or not.
If you were to accidentally misspell user
while using let
, you would receive a NameError
error.
To me, it seems as if using let
to define variables available to use throughout your tests is the better and safer way to go. before
does serve a purpose, such as performing tasks before a test as you can see in the example above, but I wouldn’t use it to query the database and define variables to use throughout your tests.
Final Thoughts
Now we’ve learned about a few of the common hooks and a very common helper method that are used when building RSpec tests! Please note that there are MANY more that could be discussed, so please feel free to google for more or take a look at my sources which name a few others as well.
While writing this post, I had an “ah-ha” moment and was able to fix a few different errors that I had been having for 2 weeks now in my project that I’m building alongside writing these posts. This is exactly why I love writing technical posts. I gain just as much knowledge and learn new things while researching and writing as y’all do from reading my posts. It’s always incredibly rewarding, so thank you all for continuing to read my stuff and motivating me to write weekly.
Note: This weeks cover image is brought to you from my travels to the small island of Utila, Honduras 2 years ago!
Sources
Before Vs Let
The Definitive RSpec Tutorial With Examples
RSpec - Hooks
Top comments (0)