概要
Rakeのspecについて実行方法をググると後述する冗長な書き方(×今までのよくある書き方)しか出てこず、自社のサービスも全て同じ書き方がされていてムズムズしたので
Rakeのspecをシンプルに書くためのヘルパークラスrake_helper.rbを作成しました。
このヘルパークラスを使用することにより、Rakeタスクのspecのコードがシンプルになり、テストスイートの実行時間が多少短縮されるかも。
ヘルパークラス
# frozen_string_literal: true
RSpec.configure do |config|
# Load all Rake task files once into your Rails application
config.before(:suite) do
Rails.application.load_tasks
end
# Reset all Rake tasks so that the same task can be run multiple times
config.before do
Rake.application.tasks.each(&:reenable)
end
end
使い方
×今までのよくある書き方
require 'rails_helper'
# rubocop:disable RSpec/BeforeAfterAll, RSpec/InstanceVariable
describe 'ClassName' do
before(:all) do
@rake = Rake::Application.new
Rake.application = @rake
Rake.application.rake_require('task_name', [Rails.root.join('lib/tasks').to_s], [])
Rake::Task.define_task(:environment)
end
before(:each) { @rake['task_name'].reenable }
# test
# Run with something like "@rake['task_name'].invoke"
end
# rubocop:enable RSpec/BeforeAfterAll, RSpec/InstanceVariable
○ヘルパークラスを用いた書き方
require 'rails_helper'
require 'rake_helper' # Just add this line!
# test
# Run with something like "Rake.application['task_name'].invoke"
つまずいたところ
ローカル環境にrake_helper.rbを用意し、一部の既存specで利用するよう変更したら正常に実行完了しましたが、
GitHub Actionsのspecではランタイムエラー(Don't know how to build task)が発生しました。
原因は、rake_helper.rbの:suiteでRails.applicationに全タスクをロードした後、
既存specがタスクを1件だけロードして上書き(×今までのよくある書き方)していたからです。
対応として、上記に該当する全ての既存specでrake_helper.rbを利用するよう変更したら解決しました。
ぼやき
-
rake_helper.rb内でrequire 'rails_helper'をしたら呼出し側Rakeのspecのrequire 'rails_helper'を減らせる(1行にできる)かと思いましたが、ヘルパークラスはそれぞれ1つの責任を持っているので分割した。が、今思えばやっても大きな問題にはならなさそう。 - 逆に
rails_helper.rb内でrequire 'rake_helper'することもできましたが、それをするとRake以外のspecでもrake_helperが無駄に実行されてしまう。その場合、type: :rakeのときだけbeforeを実行するようなロジックが必要となり、呼出し側Rakeのspecの全実行箇所に(type: :rake)を追記することになるので冗長かなと思ってやめました。