Lesson Weekend

We should test the association between Albums and Songs before we move on to building the rest of our application. Let's start by adding a models folder inside our spec directory. Note: if your project doesn't have a spec folder, you need to run the following command: bundle exec rails generate rspec:install.

Next, add two files to models: album_spec.rb and song_spec.rb. This is an example where specific naming is required — the folder must be named models and each model specification should follow the pattern <model name>_spec.rb.

Let's create the basic structure for album_spec.rb. The structure for song_spec.rb will look exactly the same other than the class name.

spec/models/album_spec.rb
require 'rails_helper'

describe Album do
  # Tests will go here.
end

We need to require our rails_helper file just as we required spec_helper with Sinatra.

We're ready to write our first test. Let's make sure that an Album can have many Songs. We've already confirmed this manually in the Rails console but we should always have actual tests as well.

We could create our test so it looks something like this:

spec/models/album_spec.rb
...
describe Album do
  it("has many songs") do
    album = Album.create(name: "album")
    song1 = Song.create(name: "song1", album_id: album.id)
    song2 = Song.create(name: "song2", album_id: album.id)
    expect(album.songs()).to(eq([song1, song2]))
  end
end

However, this test is boilerplate and tedious, especially if we have a large application with many associations.

It would be nice if we had a way to simplify this. Fortunately, there's a gem called shoulda-matchers that can make writing tests easier. Let's add the following to our Gemfile after the other group blocks:

Gemfile
group :test do
  gem 'shoulda-matchers'
end

This gem will only be used for testing, which is why it's in the :test group. Any gem that we want to use only for testing will go inside this code block. Make sure to save and bundle.

Next, we need to add the following to the end of our rails_helper.rb file:

spec/rails_helper.rb
Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    with.test_framework :rspec
    with.library :rails
  end
end

Now we're ready to write a test that takes advantage of shoulda-matchers:

spec/models/album_spec.rb
require 'rails_helper'

describe Album do
  it { should have_many(:songs) }
end

That's it. shoulda-matchers reduces our test to a single line of code. If we run rspec, the test will pass.

Let's also test that a Song has an Album:

spec/models/song_spec.rb
require 'rails_helper'

describe Song do
  it { should belong_to(:album) }
end

shoulda-matchers also has many other useful matchers. We will only cover using this tool for associations and for validations, which we'll go over later in this course section. From here on out, test all associations between classes with shoulda-matchers.

For a full list of the matchers available and some examples, check out the shoulda-matchers documentation, specifically the sections on Matchers for ActiveRecord and ActiveModel.

Lesson 8 of 34
Last updated August 7, 2022