Skip to content

Instantly share code, notes, and snippets.

@hiroki-uchida
Last active December 7, 2023 07:26
Show Gist options
  • Save hiroki-uchida/16d17ec080c35479dbebb8025a3a8a88 to your computer and use it in GitHub Desktop.
Save hiroki-uchida/16d17ec080c35479dbebb8025a3a8a88 to your computer and use it in GitHub Desktop.
RSpec で Rake Task のテストをクリーンに書く
# File: spec/tasks/send_invoices_spec.rb
require "rails_helper"
describe "rake billing:send_invoices", type: :task do
it "Rails environment を読み込んでいること" do
expect(task.prerequisites).to include "environment"
end
it "送信対象が存在しないとき、エラーにならないこと" do
expect { task.execute }.not_to raise_error
end
it "ログが標準出力されること" do
expect { task.execute }.to output("請求書を送信中\n").to_stdout
end
it "Dead Mans Snitchにチェックインされること" do
dead_mans_snitch_request = stub_request(:get, "https://nosnch.in/c2354d53d2")
task.execute
expect(dead_mans_snitch_request).to have_been_requested
end
it "送信対象が存在するとき、メールが配信されること" do
subscriber = create(:subscriber)
task.execute
expect(subscriber).to have_received_invoice
end
matcher :have_received_invoice do
match_unless_raises do |subscriber|
expect(last_email_sent).to be_delivered_to subscriber.email
expect(last_email_sent).to have_subject '今月の請求書です'
...
end
end
end
require "rails_helper"
describe "rake hoge", type: :task do
it 'エラーにならないこと' do
expect { task.execute }.not_to raise_error
end
it "ログが標準出力されること" do
expect { task.execute }.to output("hogeを実行中\n").to_stdout
end
end
# File: spec/rails_helper.rb
# `RSpec.config` の前あたりに追加
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
# File: spec/support/tasks.rb
require "rake"
# トップレベルの `describe` にタスク名を入れて使う。
# タスク名は "rake " をつけても同じように動作する。
#
# 1) describe "foo:bar" do ... end
# 2) describe "rake foo:bar" do ... end
#
# 2はドキュメント生成時にわかりやすくするために用意してある。
module TaskExampleGroup
extend ActiveSupport::Concern
included do
let(:task_name) { self.class.top_level_description.sub(/\Arake /, "") }
let(:tasks) { Rake::Task }
# テストの中で `task` として Rake task を呼び出せるように設定
subject(:task) { tasks[task_name] }
end
end
RSpec.configure do |config|
# タグとして `:task` を設定する、もしくは `spec/tasks` にspecファイルを設置する。
config.define_derived_metadata(:file_path => %r{/spec/tasks/}) do |metadata|
metadata[:type] = :task
end
# type: :task を定義
config.include TaskExampleGroup, type: :task
config.before(:suite) do
Rails.application.load_tasks
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment