Test Rake Tasks

后端 未结 6 946
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-31 18:28

I am developing a ROR app that relies on many custom Rake tasks.

What is the best way to test them?

相关标签:
6条回答
  • 2021-01-31 18:58

    This is pretty well covered in another SO question

    My recommendation, repeated here in summary, is not to try testing rake tasks: extract the code to be tested to a class, model or lib function and test it there. Then just use rake to call the functions and manage dependencies.

    0 讨论(0)
  • 2021-01-31 18:59

    Well, now there's a Gem for that:

    Fantaskspec - https://github.com/crismali/fantaskspec

    0 讨论(0)
  • 2021-01-31 19:01

    I like the PivotalLabs' way the most. However, I generalized and modified their code as followed in my app:

    # file: spec/tasks/my_rake_file_spec.rb
    require 'spec_helper'
    require 'rake'
    
    describe 'my_rake_file.rake' do
      before :all do
        Rake.application.rake_require 'tasks/my_rake_file'
        Rake::Task.define_task(:environment)
      end
    
      let(:run_rake_task) {
        Rake::Task[task_name].reenable
        Rake.application.invoke_task task_name
      }
    
      describe 'my_task_name' do
        let(:task_name) { "my_task_name" }
    
        it "creates 10 cars" do
          run_rake_task
          Car.count.should == 10
        end
      end
    end
    

    Also, I extracted the heavy lifting of my_rake_file.rake's code to a module, which is stored in lib/

    0 讨论(0)
  • 2021-01-31 19:16

    Rake tasks do need testing, especially if you do some batch processing in it. Testing them is quite easy these days:

    class CleanExamsTaskTest < ActiveSupport::TestCase
      def test_deletes_results_of_old_exams
        travel_to Time.zone.parse('2010-07-05 10:00')
        @exam.update!(end: Time.zone.parse('2010-07-04 09:59'))
    
        assert_difference -> { @exam.answered_questions.count }, -1 do
          capture_io { run_task }
        end
      end
    
      def test_output
        travel_to Time.zone.parse('2010-07-05 10:00')
        @exam.update!(end: Time.zone.parse('2010-07-04 09:59'))
    
        assert_output("Exams processed: 1\n") { run_task }
      end
    
      private
    
      def run_task
        Rake::Task['exams:clean'].execute
      end
    end
    

    Full example

    Tested with Ruby >= 1.9 and Rails 5.2. Uses Minitest from stdlib. No other dependencies.

    0 讨论(0)
  • 2021-01-31 19:22

    Something like:

      def execute_rake(file,task)
        require 'rake'
        rake = Rake::Application.new
        Rake.application = rake
        Rake::Task.define_task(:environment)
        load "#{Rails.root}/lib/tasks/#{file}"
        rake[task].invoke
      end
    

    At your spec:

    execute_rake("tags.rake","tags:popular")
    
    0 讨论(0)
  • 2021-01-31 19:25

    Rake tasks are pretty hard to test. The easiest solution would be to move the logic into a method in an appropriate model. You can then test that and just call the method from the rake task.

    0 讨论(0)
提交回复
热议问题