Deepak
Deepak

Reputation: 361

How to write unit test cases for rake tasks in rails?

Hi all I have this situation , I need to write unit test cases for rake tasks in my rails application but i could not figure out a way to do that. Did any one try that ?

Upvotes: 3

Views: 2385

Answers (3)

LondonAppDev
LondonAppDev

Reputation: 9663

In my opinion, the cleanest way to do this is to abstract the logic you want to test into a separate class, and test that.

Then the rake task becomes a wrapper around the logic you want to test.

For example, let's say you want to create a rake task called "my_task" that is testable.

lib/tasks/my_task.rb

class MyTask
  def initialize(args = {})
    @args = args
  end

  def run
    # Task logic here (broken down into methods if needed)
  end
end

lib/tasks/my_task.rake

require 'tasks/my_task'

task :my_task, %i[foo bar] => :environment do |_t, args|
  args = args.to_hash.symbolize_keys
  MyTask.new(args).run
end

Assuming you are using minitest, the test would look like this:

test/lib/tasks/my_task_test.rb

require 'test_helper'
require 'tasks/my_task'

class MyTaskTest < ActiveSupport::TestCase
  test 'my task works' do
    MyTask.new({...}).run
  end
end

This means you don't need to invoke or import tasks in the test runner.

Reference: Reddit: How do you write unit tests for Rake tasks added to a Rails project?.

Upvotes: 0

adil hussain
adil hussain

Reputation: 910

I found out this link for writing test cases using rspec. Short and crisp test cases

Basically, create a module which will parse the name of the rake task, and make us available the keyword task, on which we could call expect { task.execute }.to output("your text\n").to_stdout

Here's how you will create the file,

module TaskExampleGroup extend ActiveSupport::Concern

    included do
    let(:task_name) { self.class.top_level_description.sub(/\Arake /, "") }
    let(:tasks) { Rake::Task }

    # Make the Rake task available as `task` in your examples:
    subject(:task) { tasks[task_name] }
    end
end

Add this in the rspec initializer file

RSpec.configure do |config|

    # Tag Rake specs with `:task` metadata or put them in the spec/tasks dir
    config.define_derived_metadata(:file_path => %r{/spec/tasks/}) do |metadata|
    metadata[:type] = :task
    end

    config.include TaskExampleGroup, type: :task

    config.before(:suite) do
    Rails.application.load_tasks
    end
end

Upvotes: 0

rajibchowdhury
rajibchowdhury

Reputation: 5554

What you can do is this..

  1. Write your logic which will run on a rake task inside a model or class.

  2. Write unit test for that model.

  3. Finally call that method inside your rake task.

Upvotes: 4

Related Questions