Building Tests in Ruby: RSpec Helper Methods and Hooks
Tags: ruby, codenewbie, testing, webdev
Published: 2019-08-09 21:04:29

---
title: Building Tests in Ruby: RSpec Helper Methods and Hooks
published: true
description: A description of a few RSpec hooks and a helper method.
tags: ruby, codenewbie, testing, webdev
series: Building Tests in Ruby
cover_image: https://thepracticaldev.s3.amazonaws.com/i/6sce77o0x1bpv6nyvl7w.png
---

Two weeks ago I started this series with [this post](https://dev.to/torianne02/building-tests-in-ruby-the-basics-59mo). 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. 

![code showing after hooks](https://thepracticaldev.s3.amazonaws.com/i/75vo0vroxeouwsgtaniq.png)

Take a moment and consider what order you think these would print out in before looking below this line!

![answers to above code](https://thepracticaldev.s3.amazonaws.com/i/mvrzgzoqjmj8gh32iack.png)

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. 

![code showing before hooks](https://thepracticaldev.s3.amazonaws.com/i/34mhyb8kfz23x05vvpja.png)

Again, let's see if you can guess the correct order of output!

![answers of before hooks code](https://thepracticaldev.s3.amazonaws.com/i/9hf7yaxsw2rm9hqm6zyg.png)

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. 

![side by side comparison of before and let](https://thepracticaldev.s3.amazonaws.com/i/zyn157e2dta7hbvemnpb.png)

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. 

![code showing non-error when using typo](https://thepracticaldev.s3.amazonaws.com/i/e9cpivph1e08v7isclbe.png)

If you were to accidentally misspell `user` while using `let`, you would receive a `NameError` error. 

![code showing error message when typo](https://thepracticaldev.s3.amazonaws.com/i/7w3ibf0j83ptlzo4may7.png)

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](https://launchacademy.com/codecabulary/learn-test-driven-development/rspec/before-vs-let)
[The Definitive RSpec Tutorial With Examples](https://www.rubyguides.com/2018/07/rspec-tutorial/)
[RSpec - Hooks](https://www.tutorialspoint.com/rspec/rspec_hooks.htm)