Stand out by understanding RSpec

Stand out by understanding RSpec

·

4 min read

RSpec is a Rails gem designed to make it easy to write unit and feature tests. If you run into any trouble, you can read the docs here

Throughout my career and especially while job-hunting, the number one piece of advice I was given was to write unit tests.

In any given situation, be it a take-home exam or a portfolio piece, if you write tests it will show that you're a thoughtful engineer who takes time to think through problems.

And your code will be better for it.

In this article we'll talk through how you can get RSpec running, the basics of writing your first unit tests, and some nifty features in RSpec to help keep your tests clean and organized.

Let's dive in:

Installing RSpec

Before you can start writing tests with RSpec, you'll need to install the gem and set up your Rails application. To get started, follow these steps:

  1. Open your Gemfile and add the rspec-rails gem to the development and test group:
group :development, :test do
  gem 'rspec-rails', '~> 5.0'
end
  1. Install the gem by running bundle install

  2. Run the RSpec generator with rails generate rspec:install. This command creates a .rspec file, a spec folder, and a spec_helper.rb file in your project directory.

After this is configured, you're ready to write your first unit test!

Writing our first tests

With RSpec installed, let's create a simple model and write a unit test to ensure it's working correctly.

  1. For this example, we'll create a User model with a name attribute. Run rails generate model User name:string to generate the necessary files. You'll have to run a migration for this change to be added to your database.

  2. Add the following code to our model to validate the presence of a name field:

     class User < ApplicationRecord
       validates :name, presence: true
     end
    
  3. Note that in the spec folder, a new folder called models, and inside it, a file named user_spec.rb has been generated. This is where we'll write our tests for the User model.

  4. Open user_spec.rb and start by creating a new describe block for the User model and write a simple test to check if a user with a valid name can be created

     RSpec.describe User do
       it 'is valid with a name' do
         user = User.new(name: 'John Doe')
         expect(user).to be_valid
       end
    
       it 'is not valid without a name' do
         user = User.new
         expect(user).to_not be_valid
       end
     end
    
    1. To execute your test, run bundle exec rspec in your terminal. If everything is set up correctly, you should see an output indicating that the test passed.

You can now write additional tests for your User model or any other part of your application by following the same pattern within the spec folder.

Extra features

While none of these are necessary to function, RSpec does have a whole host of cool features that help promote clean and organized unit tests.

It's easy for these files to get long and unwieldy, so keeping your codebase clean and DRY will demonstrate expertise.

Below, I'll detail each of RSpec's interesting features that we use regularly in our day-to-day development work, as well as a code example to demonstrate what I mean.

Context blocks

The context method helps create logical groups for your tests based on specific conditions or scenarios.

This can make your tests more readable and better organized.

RSpec.describe User do
  context 'when name is present' do
    let(:user) { User.new(name: 'John Doe') }

    it 'is valid' do
      expect(user).to be_valid
    end
  end

  context 'when name is not present' do
    let(:user) { User.new }

    it 'is not valid' do
      expect(user).to_not be_valid
    end
  end
end

Shared examples

RSpec allows you to define reusable examples that can be included in multiple test groups, helping you keep your tests DRY.

shared_examples 'a valid user' do
  it 'is valid' do
    expect(user).to be_valid
  end
end

describe AdminUser do
  let(:user) { AdminUser.new(name: 'John Doe') }

  it_behaves_like 'a valid user'
end

describe RegularUser do
  let(:user) { RegularUser.new(name: 'Jane Doe') }

  it_behaves_like 'a valid user'
end

Custom matchers

RSpec allows you to create custom matchers that make your tests more expressive and readable.

RSpec::Matchers.define :be_a_valid_user do
  match do |user|
    user.valid?
  end
end

describe User do
  let(:user) { User.new(name: 'John Doe') }

  it 'is valid with a name' do
    expect(user).to be_a_valid_user
  end
end

Final thoughts

As someone who's been involved both in interviewing and in hiring, I've seen that one of the top ways a candidate can stay out is by writing a suite of thoughtful unit tests.

It's an immediate signal to the hiring team that you're a professional and you know what you're doing.

Use this post as a reference and write some tests!

Thanks for reading

Austin