# Stand out by understanding RSpec

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](https://rspec.info/documentation/)

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:
    

```ruby
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:
    
    ```ruby
    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
    
    ```ruby
    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.

```ruby
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.

```ruby
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.

```ruby
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
