Reputation: 361
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
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
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
Reputation: 5554
What you can do is this..
Write your logic which will run on a rake task inside a model or class.
Write unit test for that model.
Finally call that method inside your rake task.
Upvotes: 4