Search code examples
ruby-on-railsrspecgrape-apisimplecov

SImplecov - Incorrect test coverage for Grape API


I have a Rails 4.2 app with an API based on Grape. I started to write tests for it using Rpsec. My tests work great and test what I expected. But when I run rspec at terminal, Simplecov is not showing the correct coverage for the api files, as you can see on the image bellow.

Simplecov

The files on the dir /lib/api/app do have some coverage. But Simplecov shows them as 0% covered.

To compare, I ran specs inside RubyMine with the built in coverage tool, and it shows the correct coverage:

enter image description here

So, am I missing something here? whats wrong with simplecov?

this is my rails_helper.rb :

ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)

abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
require 'simplecov'
SimpleCov.start 'rails'

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }


ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|

  config.include RSpec::Rails::RequestExampleGroup, type: :request, file_path: /spec\/api\/v1/


  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  config.use_transactional_fixtures = false


  config.infer_spec_type_from_file_location!

  Faker::Config.locale = 'pt-BR'

end

This is one of API endpoints, trips.rb:

module Api
  module App
    class Trips < Grape::API
      include Grape::Kaminari
      resource :trips do
        desc 'Return a list of trips of a vehicle.'
        params do
          requires :vehicle_id, type: Integer, desc: 'id of the vehicle'
          optional :page, type: Integer, desc: 'Page of registers. Default to 1 (first page).'
          optional :per, type: Integer, desc: 'Number of registers per page. Default to 25.'
        end
        get do
          vehicle = Vehicle.find params[:vehicle_id]
          if vehicle.user == current_user
            trips = Trip.where(vehicle_id: vehicle.id ).order(started_at: :desc)

            present paginate(trips), with: Entities::Trip
          else
            error!('Unauthorized', 401)
          end
        end

        desc 'Return a Trip'
        params do
          requires :id, type: Integer, desc: 'id of the Trip'
        end

        route_param :id do
          get do
            trip = Trip.find params[:id]
            if trip.vehicle.user == current_user
              present trip, with: Entities::Trip
            else
              error!('Unauthorized', 401)
            end

          end
        end

      end
    end
  end
end

And this is a example spec that should be 100% covered (trips_spec.rb):

describe Api::App::Trips do
  include ApiHelpers

  let(:user)          { create(:user) }
  let(:user2)         { create(:user) }
  let(:vehicle)       { create(:vehicle, user_id: user.id) }
  let(:vehicle2)      { create(:vehicle, user: user2) }
  let(:trip)          { create(:trip, vehicle: vehicle) }
  let(:trip2)         { create(:trip, vehicle: vehicle2) }
  let(:auth_headers)  { user.create_new_auth_token }




  describe 'GET /api/v1/trips/:id' do

    context 'when not authenticated' do
      it 'returns 401 unauthorized' do
        get "/api/v1/trips/#{trip.id}"
        expect(response).to have_http_status(401)
      end
    end

    context 'when user owns the vehicle' do

      it 'returns a trip by id' do
        get "/api/v1/trips/#{trip.id}", nil, auth_headers
        expect(response.status).to eq(200)
        expect(json_response).to be_an Hash
      end
    end

    context 'when vehicle is from another user' do

      it 'returns error 404' do
        get "/api/v1/trips/#{trip2.id}", nil, auth_headers
        expect(response.status).to eq(401)
      end
    end

  end

  describe 'GET /api/v1/trips' do

    context 'when user owns the vehicle' do

      it 'returns a list of trips by vehicle id' do
        get "/api/v1/trips?vehicle_id=#{vehicle.id}", nil, auth_headers
        expect(response.status).to eq(200)
        expect(json_response).to be_an Array
      end
    end

    context 'when vehicle belongs to another user' do
      it 'returns error 404' do
        get "/api/v1/trips?vehicle_id=#{vehicle2.id}", nil, auth_headers
        expect(response.status).to eq(401)
      end
    end

  end

end

Solution

  • So, I figured out the problem: I was invoking Simplecov on rails_helper.rb. The correct place to invoke it is on spec_helper.rb, at the very beginning .