In the last episode we saw how to create our Gem and its structure. In today's episode we will test everything we did.

Rspec

We have a rspec folder where all our tests are located.

bundle exec rspec

We got an error because we need to fix our gemspec file.

The validation error was '"FIXME" or "TODO" is not a description

Let's fix that!

Now if we run rspec, it should be fine.

bundle exec rspec

From the last episode, we forgot to move the version file inside formulae_ruby. Let's move that.

One test failed. Let's remove it That was just to see if it was working.

require 'spec_helper'

RSpec.describe FormulaeRuby do
  it 'has a version number' do
    expect(FormulaeRuby::VERSION).not_to be nil
  end

  it 'does something useful' do
    expect(false).to eq(true)
  end
end

Resources tests

Before starting our tests, let's add json and byebug in our spec helper. We might want to use it later, especially JSON.

vim spec/spec_helper.rb
require 'byebug'
require 'json'

We need to organize our tests. Let's create a folder for our resources tests.

mkdir spec/resources

And we will create a form_spec file:

vim spec/resources/form_spec.rb

For our test, we will pass some JSON to our Form and wel check if the form responds to specific methods, our attributes.

require 'spec_helper'

RSpec.describe FormulaeRuby::Form do
  let(:json) do
    JSON.parse({
      id: '1',
      application: {
        id: '1'
      },
      sections: [
      ],
      questions: [
      ]
    }.to_json)
  end
  let(:form) { FormulaeRuby::Form.new(json) }

  describe 'fields' do
    it { expect(form).to respond_to(:id) }
    it { expect(form).to respond_to(:application_id) }
    it { expect(form).to respond_to(:questions) }
    it { expect(form).to respond_to(:sections) }
  end
end

Let's make tests to our Sections:

vim spec/resources/section_spec.rb

We will pass some JSON to our Section and check if the model responds to the correct keys.

require 'spec_helper'

RSpec.describe FormulaeRuby::Section do
  let(:json) do
    JSON.parse({
      id: 1,
      form_id: 1,
      name: 'name',
      order: 1,
      content: 'content'
    }.to_json)
  end
  let(:section) { FormulaeRuby::Section.new(json) }

  describe 'fields' do
    it { expect(section).to respond_to(:id) }
    it { expect(section).to respond_to(:form_id) }
    it { expect(section).to respond_to(:name) }
    it { expect(section).to respond_to(:order) }
    it { expect(section).to respond_to(:content) }
  end
end

Let's do the same thing to our Questions:

vim spec/resources/question_spec.rb

We will check if the keys are correct.

require 'spec_helper'

RSpec.describe FormulaeRuby::Question do
  let(:json) do
    JSON.parse({
      id: '1',
      key: 'key',
      label: 'label',
      order: 1,
      content: 'content'
    }.to_json)
  end
  let(:question) { FormulaeRuby::Question.new(json) }

  describe 'fields' do
    it { expect(question).to respond_to(:id) }
    it { expect(question).to respond_to(:key) }
    it { expect(question).to respond_to(:label) }
    it { expect(question).to respond_to(:order) }
    it { expect(question).to respond_to(:content) }
  end
end

This covers test for our resources. Let's work with the client tests.

Client tests

For the moment, we just have one client: the FormClient. This client has two methods: all and find. Each of these methods make HTTP requests to our API and if we don't have our API running locally or remotely our tests will fail.

We shouldn't rely on our API to make tests. Additionally, our tests make HTTP requests. It can make our API slow, especially if your API has a rate limit.

We will use webmock and vcr.

Let's add these in our gemspec:

vim formulae_ruby.gemspec
  spec.add_development_dependency 'vcr'
  spec.add_development_dependency 'webmock'

Let's do a bundle install, and install these gems.

bundle install

And change our spec_helper:

VCR.configure do |c|
  c.cassette_library_dir = "test/fixtures"
  c.hook_into :webmock
end

As we are using webmock, it will not make a real HTTP request. It intercepts all the requests we made, and then we can return the result of the request. The return of the request will be generated by VCR. We will have a cassette or a fixture file that will be the result of our HTTP request.

The first time, VCR will download the JSON and store it in the file. After the first time, all requests will check the fixture file. In our case, the fixture files will be located in test/fixtures.

Let's do our first test for our FormClient.

mkdir spec/clients
vim spec/clients/form_client_spec.rb

In our test, we will use a cassette called all_forms. We will run two tests. One to count the number of forms, and another to count the number of questions in the first form.

require 'spec_helper'

RSpec.describe FormulaeRuby::FormClient do
  let(:form_client) { FormulaeRuby::FormClient.new(application_id: 1) }

  describe '#all' do
    it 'checks all the forms we have' do
      VCR.use_cassette('all_forms') do
        response = form_client.all
        expect(response.count).to eq 68
        first_form = response[0]
        expect(first_form.questions.count).to eq 7
      end
    end
  end
end

Let's see how our fixture looks like.

vim test/fixtures/all_forms.yml

Our API is running, so it gets the JSON from our API.

Let's go back to our test, and make a test for our find method.

  describe '#find' do
    it 'returns a form by a specific id' do
      VCR.use_cassette('specific_form') do
        response = form_client.find(1)
        expect(response.questions.count).to eq 7
        expect(response.application_id).to eq 1
        expect(response.respond_to?(:application_id)).to be_truthy
        expect(response.respond_to?(:questions)).to be_truthy
        expect(response.respond_to?(:sections)).to be_truthy
      end
    end
  end

The method find returns a form. So, we will check the quantity of questions. We will also check the keys.

Let's run our test suite, and see if everything is ok. It passes!

We can also see the fixture it has created.

Summary

Today we saw how to test our gem, make model tests, and test HTTP requests. Tomorrow, we will see how to deploy our application.

Resources