Simplecov: Code Coverage for rake tasks

Created on 5 Feb 2015  路  5Comments  路  Source: simplecov-ruby/simplecov

Hi there,

we have some rake tasks including specs. Unfortunately we do not get code coverage for these rake tasks. Maybe it's an issue of the file extension .rake. Is there a possibility to include .rake files?

Support

Most helpful comment

SOLVED - UPDATED

My original solution here worked, but I ran into problems with coverage results getting clobbered by subsequent tasks specs. One of those _you get results for the last test_ situations. I solved it by moving the task loading out of the shared_context entirely, so it's only ever executed once.

spec/support/shared_contexts/rake.rb

# https://github.com/colszowka/simplecov/issues/369

shared_context "rake" do
  let(:task_name) { self.class.top_level_description }
  subject         { Rake.application[task_name] }

  # This allows tasks to be invoked more than once.
  before do
    subject.reenable
  end
end

spec/rails_helper.rb

require 'simplecov'
ENV["RAILS_ENV"] ||= 'test'

require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'

# Load rake tasks so they can be tested.
Rake.application = Rake::Application.new
Rails.application.load_tasks

...

screen shot 2017-07-06 at 2 15 43 pm

All 5 comments

Unrelated to your problem, it's a best practice not to test Rakefiles. Any code that you'd put in a rakefile should call out to something in e.g. lib that you test.

SimpleCov just uses the Ruby stdlib Coverage module. Since Rakefiles are Ruby, they should be included unless either they are filtered out by location or are loaded before SimpleCov.start.

If you have any more questions, please paste your simplecov config, how you run your tests, your simplecov version, your ruby, your rake file location, and where you require simplecov.

If you solve you problem, please write up what helped and close the issue. Thanks :)

Please also review https://github.com/colszowka/simplecov/blob/master/CONTRIBUTING.md and https://github.com/colszowka/simplecov/issues/340

I'm running into this issue: I'm using SimpleCov with rspec and cucumber and a shared .simplecov file.

# .simplecov
SimpleCov.start do
  use_merging true
  merge_timeout 20 * 60
  coverage_dir 'doc/build/coverage'

  add_filter '/spec/'
  add_filter '/vendor/'
  add_filter '/config/'

  add_group 'Libraries', 'lib'
  add_group 'Controllers', 'app/controllers'
  add_group 'Models', 'app/models'
  add_group 'Helpers', 'app/helpers'
  add_group 'Services', 'app/services'
  add_group 'Mailers', 'app/mailers'
  add_group 'Views', 'app/views'
  add_group 'Workers', 'app/workers'
end
# spec_helper.rb
ENV["RAILS_ENV"] ||= 'test'

#Conditionally enable simplecov
if ENV["COVERAGE"]
  require 'simplecov'
end

require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
# etc

There's a similar setup in the cucumber files, but it doesn't affect this at all.

The specs in question use the methodology from thoughtbot:

require "rake"

shared_context "rake" do
  let(:rake)      { Rake::Application.new }
  let(:task_name) { self.class.top_level_description }
  let(:task_path) { "lib/tasks/#{task_name.split(":").first}" }
  subject         { rake[task_name] }

  def loaded_files_excluding_current_rake_file
    $".reject {|file| file == Rails.root.join("#{task_path}.rake").to_s }
  end

  before do
    Rake.application = rake
    Rake.application.rake_require(task_path, [Rails.root.to_s], loaded_files_excluding_current_rake_file)

    Rake::Task.define_task(:environment)
  end
end

And the tests look like this:

describe 'namespace:task_name' do
  include_context 'rake'

  it 'does something helpful' do
    SomeClass.should_receive(:method).with('args')
    subject.invoke
  end
end

Generally only whichever task is last run from a file in the spec is shown as covered by SimpleCov.

So if the .rake file looked like this:

```ruby
namespace :namespace do
  desc 'first task'
  task :first => :environment do
    thing_to_test
  end

  desc 'second task'
  task :second => :environment do
    thing_to_test
  end
end

And rspec ran the tests like:

namespace:second
  does something
namespace:first
  does something

Only the first task would show green on the line with thing_to_test. The second would show it wasn't covered, even though the test had run successfully.

I'm not tied to the implementation from Thoughtbot, though it'd take some work to research and figure out an alternative if that's what's causing the problem.

Any thoughts would be helpful.

Hi there,

without digging too deep into the thoguhtbot way there it seems like it would reload files, which messes with coverage.

I can just echo the thoughts of @bf4 - just make the rake task call out to something else and test that.

task :first => :environemnt do
  MyServiceObject.new(some_parameter).call
end

then test MyServiceObject that should all be coverd neatly :)

Has anyone figured out how to get coverage on vanilla rake tasks?
My setup is largely based on the great 2011 guide: https://robots.thoughtbot.com/test-rake-tasks-like-a-boss

My tasks are more than a trigger for some other method. Here's an example:

namespace :import do
  desc "Import Photos from Wordpress"

  task photos: :environment do |task|
    log = ProcessLog.create(key: task.to_s)
    begin
      Parallel.each(Person.active, in_processes: MAX_PROCESSES) do |person|
        person.import_photo
      end
    rescue => e
      log.fail!(comment: e.to_s)
    end
    log.success!
  end
end

I'm logging when the task was run, how long it took, if it failed and with what error message. I could create a class method on Person or a service object as discussed above, but the logic of import_photo is tested elsewhere already anyway.

I want to test that the task actually works before it fails in production. I also test that all my tasks have the desc line so they'll show up in rake -T That really only fits in a task spec...

TL;DR

I test my tasks fully, but sure would like to be able to show it.

screen shot 2017-07-06 at 12 52 42 pm

SOLVED - UPDATED

My original solution here worked, but I ran into problems with coverage results getting clobbered by subsequent tasks specs. One of those _you get results for the last test_ situations. I solved it by moving the task loading out of the shared_context entirely, so it's only ever executed once.

spec/support/shared_contexts/rake.rb

# https://github.com/colszowka/simplecov/issues/369

shared_context "rake" do
  let(:task_name) { self.class.top_level_description }
  subject         { Rake.application[task_name] }

  # This allows tasks to be invoked more than once.
  before do
    subject.reenable
  end
end

spec/rails_helper.rb

require 'simplecov'
ENV["RAILS_ENV"] ||= 'test'

require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'

# Load rake tasks so they can be tested.
Rake.application = Rake::Application.new
Rails.application.load_tasks

...

screen shot 2017-07-06 at 2 15 43 pm

Was this page helpful?
0 / 5 - 0 ratings

Related issues

andyhite picture andyhite  路  8Comments

doublephi picture doublephi  路  6Comments

juanbrein picture juanbrein  路  4Comments

vkodimut picture vkodimut  路  6Comments

rcanand picture rcanand  路  5Comments