Testing
Postman is helpful to help us test our endpoints. But, what if we have 10 endpoints? Are we really going to manually click on Postman for each one of the 10 endpoints every time we modify our code?
Postman becomes unscalable when we have 10, 50, 100 endpoints. So, instead of manual testing, we write code for automated testing. You heard it right! We are writing software to test other softwares.
Generally, we call these softwares tests or specs (specifications). Remember we have actually done this in Ruby Koans? We write code to pass tests. Here, it's the same concept. We are writing tests to test the entire MVC framework.
Rspec
We are going to use the Rspec gem for testing in Rails.
Add rspec-rails
to both the :development
and :test
groups in the Gemfile
:
...
group :development, :test do
gem 'rspec-rails', '~> 3.5'
...
end
...
Install new gems by running $ bundle install
.
Initialize the spec/
directory (where specs will reside) with: $ rails generate rspec:install
. As you can guess, Rspec calls tests specs, hence the specs
folder.
$ rails generate rspec:install
create .rspec
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb
Great! Now, let's run the specs with $ rspec
$ rspec
No examples found.
Finished in 0.00039 seconds (files took 0.35769 seconds to load)
0 examples, 0 failures
As expected, we haven't written any specs yet, so there are no examples and no failures.
Rspec can be used to test the entire MVC framework, including but not limited to:
- Model Specs
- Controller Specs
- Helper Specs
- Integration Specs
Again, we have a way to generate these specs files. To generate a controller spec, run:
$ rails g rspec:controller books
create spec/controllers/books_controller_spec.rb
The format here is rails g rspec:<type of spec> <name of spec>
.
In spec/controllers/books_controller_spec.rb
,
require 'rails_helper'
RSpec.describe BooksController, type: :controller do
end
So now, let's replicate what we had in Postman to test the POST /books
endpoint.
We will attempt to translate the following:
Into Rspec:
RSpec.describe BooksController, type: :controller do
describe 'POST /books' do
it 'create a new book object' do
post :create, params: { name: 'Harry Potter' }
expect(Book.count).to eq(1)
end
end
end
post :create, params: { name: 'Harry Potter' }
creates a POST
request to the method create
in the BooksController
. It passes parameters as a hash { name: 'Harry Potter' }
.
expect(Book.count).to eq(1)
means that we expect Book.count
to equal to 1
.
$ rspec
.
Finished in 0.04074 seconds (files took 3.17 seconds to load)
1 example, 0 failures
And, our first test has passed!