Throughout my time in bootcamp, the learning environment was built off of tests, meaning that I learned by running tests, seeing my errors, and going about debugging the code to learn what works and what doesn’t. The big catch here is that us students were never taught how to build these tests. I knew what they looked like. I vaguely understood what each line was doing, but I never understood what was happening in the background.
It wasn’t until recently that I decided that I wanted to take on the challenge of learning how to build my own tests. Something I’ve learned while looking for jobs and being involved in the tech Twitter world is that test driven development is an important skill for developers to have. TDD is a skill that I would most likely have to learn during my first role as a SWE, so I thought I’d take the leap and teach it to myself while looking for a job.
While learning to build my own tests, I came across quite a few tutorials that were helpful, but not many that broke down what each line was really doing behind the scenes. This is what has lead to me writing this blog series, Building Tests in Ruby. I want to provide beginners with the behind the scenes knowledge of RSpec tests. This being the first post in the series, I will be covering the basic structure of a RSpec test. Let’s get started!
What is TDD?
Before we dive straight in to building RSpec tests, let’s first define TDD.
Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle: first the developer writes an (initially failing) automated test cast that defines a desired improvement or new function, then produces the minimum amount of code to pass that test, and finally refactors the new code to acceptable standards.
Quote from Test Driven Development (TDD): Example Walkthrough
The general steps followed for TDD are
TDD allows developers to test the functional expectation they have for a particular feature they are building. For example, if a dev wants to create a user model they could build a test that checks to make sure that a user is created with the desired parameters. The dev would first build the test(s), run those tests, then build the user model, run tests again until passing, and then refactor their code. TDD is as simple as that!
What is RSpec?
RSpec is a domain specific language (DSL) tool used to write unit tests in Ruby. It is important to note that RSpec is considered BDD (behavior driven development), which was created as a subcategory of TDD. You can learn more about BDD here.
Building Tests
Step 1
The first thing that you need to do when building RSpec tests is add the rspec gem to your Gemfile
and then require it in the file you’ll be writing your tests in.
Step 2: describe
Block
Now getting to actually writing our tests… The first thing that we need to code is our describe
block, which allows us to group our tests together as a collection. The describe
block allows us to tell RSpec which class we will be testing and it accepts either a class name or string as the argument.
The describe
block is our parent block for testing in Ruby, which means all of our other blocks and test components will be children to this one.
Step 3: context
Block
The first child block inside our describe
block is the context
block, which also accepts a class name or string as the argument. While context
blocks are not a necessary component to RSpec tests, they are very useful and help add more details about the tests. The context
block allows you to create subgroups. This makes it easier to test groups with different contexts, such as when a user is logged in or when a user is not logged in.
Step 4: it
Block
The essential child block of the describe
block is the it
block. it
is used to define the specific behavior of the test/test case. Just as the previous two blocks, it also accepts a class name or string as its argument, but it is customary to only pass a string to the block argument. Normally, the string argument used should include the word “should” to describe the behavior of the test.
In other words, the it
block describes the expected outcome, which brings me to my next topic, the expect
keyword. expect
is used to define the expectation of the test and verify that the expected conditions have been met.
Note: For this post I am going to cover the two most common keywords that go with expect
. In following posts, I will go into more detail of other keywords that can be used here as well.
to
and eql
The to
and eql
keywords are used alongside expect
in order to verify that the test is outputting the expected value. to
is used in the sense that we expect the response/message to be something. eql
comes in to play at this moment because it helps us finish the rest of the expect statement. We expect our response to equal something.
to
and eql
make the expect
statement easy to read, as it flows like a normal sentence. In the case of expect(message).to eq “Hello World!”
it would sound like “expect message to equal hello world!”
Note: To determine if the equality is false rather than true, you can use the keyword not_to
in place of to
.
Final Thoughts
YAY, we covered the most basic components that make up a RSpec test. We discussed three important blocks to building RSpec tests, describe
, context
, and it
, as well as keywords that can be used within them.
I hope that after reading this, you have a better understanding of why we use the different blocks and keywords that are used inside the tests. In the upcoming posts for this series, I will be covering other methods used with the expect
keyword as well as other RSpec methods, so stay tuned.
Note: This weeks cover image is brought to you from Connemara, Ireland (where my family/clan is originally from).
Sources
RSpec Tutorial
The Definitive RSpec Tutorial With Examples
Introduction to Test Driven Development (TDD)
Behaviour Driven Development for Ruby. Making TDD Productive and Fun.
Top comments (4)
Thank you, Victoria, for the post. Here's my humble addition to your thoughts.
One small (read important) thing that may become an obstacle in TDD is the fact, that first step -- writing test, implies that you should completely understand the task and have already decomposed it in your mind into small pieces.
And following the point, this is the core of software development, -- to understand and decompose the task, that can take 40-70% of the time for the task.
And writing tests in RSpec or something else is not difficult after that.
(I'm not talking here about simple scaffolded model and controller tests, but TDD for the business logic)
You are absolutely correct. Thank you so much for adding this to the discussion.
Thank you Victoria, very good introduction to testing and RSpec.
I would like to leave here a couple of links to resources on testing with the ruby included test library Minitest that supports both assertions
and expectations
Which might be useful for those leaning on having less dependencies or lighter tests:
Thank you very much for your work and time!
thanks for introducing us to importance of TDD and rspec .