Rakeタスクのテストをする方法
実装したいこと
前回の記事で実装したrakeタスクの内容をRSpecでテストしたい。
備忘録として記事に残してます。
前提
RSpec
、FactoryBot
は既に設定されているものとして記述してます。
実装
1. specディレクトリ配下にrake_helper.rb
を作成し、設定を記述する。
require 'rails_helper' require 'rake' RSpec.configure do |config| config.before(:suite) do Rails.application.load_tasks # Load all the tasks just as Rails does (`load 'Rakefile'` is another simple way) end config.before(:each) do Rake.application.tasks.each(&:reenable) # Remove persistency between examples end end
before(:suite)
:テスト実行時、ただ一度だけブロック内の処理を実行します。
Rails.application.load_tasks
:lib/tasks配下のすべての.rakeファイルを読み込んでいる。
before(:each)
:各テストケースの前にブロック内の処理を都度実行します。
Rake.application
:Rake::Application
のインスタンスを生成しており、読み込むファイルの拡張子やファイル名を定義している。 また、読み込む際のクラスも指定している。
reenable
:インスタンスを再度実行できるメソッド。Rakeタスクのテストを実行する場合、各テストケース間の結合性は邪魔になるので、各Rakeタスクを実行した履歴を消去した上で、再度利用できるようにしている。
2. specディレクトリ配下にrake_helper.rb
を作成し、設定を記述する。
テストの内容は前回の記事にも記載したように、「「公開待ち」の記事に対して、公開日時が過去になっているものがあれば、状態を「公開」に変更する」タスクを想定してある。
FactoryBot.define do factory :article do sequence(:title) { |n| "title-#{n}" } sequence(:slug) { |n| "slug-#{n}" } state { :draft } end end
require 'rake_helper' describe 'article_state:update_article_state' do subject(:task) { Rake.application['article_state:update_article_state'] } before do create(:article, state: :publish_wait, published_at: Time.current - 1.day) create(:article, state: :publish_wait, published_at: Time.current + 1.day) create(:article, state: :draft) end it 'update_article_state' do expect { task.invoke }.to change { Article.published.size }.from(0).to(1) end end
invoke
メソッドでRakeタスクを実行してある。他にはexecute
メソッドでも実行できる。