Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code Coverage for rake tasks #369

Closed
MMore opened this issue Feb 5, 2015 · 5 comments
Closed

Code Coverage for rake tasks #369

MMore opened this issue Feb 5, 2015 · 5 comments
Labels

Comments

@MMore
Copy link

MMore commented Feb 5, 2015

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?

@bf4
Copy link
Collaborator

bf4 commented Feb 8, 2015

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 #340

@bf4 bf4 added the Support label Feb 8, 2015
@sferik sferik closed this as completed Apr 19, 2015
@jheilema-nerdery
Copy link

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.

@PragTob
Copy link
Collaborator

PragTob commented Mar 18, 2017

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 :)

@duffyjp
Copy link

duffyjp commented Jul 6, 2017

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

@duffyjp
Copy link

duffyjp commented Jul 6, 2017

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

FinnWoelm added a commit to OpenlyOne/openly-rails that referenced this issue Nov 18, 2018
Code coverage for tasks was reported incorrectly due to tasks being
reloaded on every task spec. Using the solution provided by @duffyjp in
simplecov-ruby/simplecov#369 (comment)
we can simply load all tasks on initialization when generating coverage.
FinnWoelm added a commit to OpenlyOne/openly-rails that referenced this issue Nov 18, 2018
Code coverage for tasks was reported incorrectly due to tasks being
reloaded on every task spec. Using the solution provided by @duffyjp in
simplecov-ruby/simplecov#369 (comment)
we can simply load all tasks on initialization when generating coverage.
frankduncan pushed a commit to redcross/dcsops that referenced this issue May 30, 2020
The test coverage was getting reset for the rake tests because rake was
being restarted constantly.  This moves the start into the spec_helper,
so it's only started once, based on reading:

simplecov-ruby/simplecov#369

Also required moving the last_comment fix into the spec_helper since
that's how production rake runs
frankduncan pushed a commit to redcross/dcsops that referenced this issue Jun 9, 2020
The test coverage was getting reset for the rake tests because rake was
being restarted constantly.  This moves the start into the spec_helper,
so it's only started once, based on reading:

simplecov-ruby/simplecov#369

Also required moving the last_comment fix into the spec_helper since
that's how production rake runs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants