1

私はそのようなタスクを持っています/lib/crawler.rake:

namespace :crawler do
  area_names = Dir[Rails.root.join("lib", "crawler", "*.rb")].map do |file_name|
    File.basename(file_name, ".rb")
  end

  area_names.each do |area_name|
    task area_name.to_sym => :environment do
      logger = Logger.new("log/crawl_#{area_name}.log")

      # do something

      parallel_results = crawler.crawl
      mutex = Mutex.new

      Parallel.each(parallel_results, in_threads: [parallel_results.count, CRAWL_CONFIG["building_thread_max"]].min) do |pages|
        begin
          # do something
        rescue => e
          # do something
          raise e
        end
      end

      Availability.update_by_grounds_and_time
    end
  end
end

ここでのロジックは、並列処理後にすべて問題がなければ、update_by_grounds_and_timeメソッドを呼び出して updateを実行しAvailabilityます。エラーが発生した場合は、アクションを停止してエラーを発生させます。

したがって、これらのケースをテストするためにrspecを書きたいです。ここでタスクの出力をモック/スタブ化し(パスまたはエラーを発生させ)、update_by_grounds_and_timeメソッドを呼び出したかどうかを確認しますか? 本当にタスクを呼び出す必要はありませんか? 使えますRspec Mockか?

手伝って頂けますか!感謝

4

2 に答える 2

2

これらの場合に私が通常行うことは、肉を別のクラス/サービスオブジェクト/その他に抽出することです。これにより、テストがはるかに簡単になります。その後、rake タスクはそのオブジェクトの単なる呼び出し元になるため、テストする必要はありません。

于 2016-06-15T07:40:19.823 に答える
1

で定義されている場合はRakefile、これを試してください。

require 'rake'

RSpec.describe "Rake Tasks" do
  before do
    file, path = Rake.application.find_rakefile_location
    Rake.load_rakefile("#{path}/#{file}")
  end

  it "should invoke some tasks" do
    expect(Availability).to receive(:update_by_grounds_and_time)
    Rake.application["crawler:#{area_name}"].invoke
  end
end

で定義されている場合はfoo.rake、次を試してください。

require 'rake'

RSpec.describe "Rake Tasks" do
  before do
    Rake.application.rake_require('/path/to/lib/tasks/foo')
  end

  it "should invoke some tasks" do
    expect(Availability).to receive(:update_by_grounds_and_time)
    Rake.application["crawler:#{area_name}"].invoke
  end
end

UPDATE (エラーの場合)

例えば

# foo.rake
Parallel.each(parallel_results, in_threads: [parallel_results.count, CRAWL_CONFIG["building_thread_max"]].min) do |pages|
  begin
    foo = Foo.new
    foo.bar
    # do something else
  rescue => e
    # do something
    raise e
  end
end

# foo_spec.rb
require 'rake'

RSpec.describe "Rake Tasks" do
  before do
    Rake.application.rake_require('/path/to/lib/tasks/foo')
  end

  it "should not call Availability#update_by_grounds_and_time if error raised" do
    allow_any_instance_of(Foo).to receive(:bar).and_raise(StandardError)
    expect(Availability).to_not receive(:update_by_grounds_and_time)
    expect { Rake.application["crawler:#{area_name}"].invoke }.to raise_error(StandardError)
  end
end
于 2016-06-14T16:48:09.993 に答える