適当に、つらつらと

日々思った事等を適当に書いていければと。

Gem、、、じゃなくてRailsEngineのRSpecをRailsAppから呼び出せるようにした際のメモ

書き残して置かないと忘れそうなので箇条書き。

Gemの形で作成しているRailsAppRailsEngineのRSpecをどうやればスマートに実施出来るか試行錯誤中。 一旦、タイトルのようにGemをInstallしたRailsAppから呼び出せるようにしたのでメモ。

まあ、概ね公式にもある通りかな。 rakeタスクを lib/tasks 配下に作成し Rails::Railtie を継承したクラスを用意して rake_tasks 内で呼び出すようにする。

rakeタスクの例

namespace :hoge do
  desc "gems rspec"
  task :spec do
    Rspec::Core::RakeTask.new(:hoge) do |t|
      example = []
      example += ENV['spec_example'].split if ENV['spec_example'].present?
      t.rspec_opts = example.map{|ex| "-e #{ex}"}.flaten.join(' ')
      t.pattern = File.join(Gem.loaded_specs['hoge'].full_gem_path, t.pattern)
    end
    Rake::Task[:hoge].invoke
  end
end

Railtieの例

module hoge
  class Railtie < ::Rails::Railtie
    rake_tasks do
      load "tasks/rspec.rake"
    end
  end
end

こんな感じにしておいて、あとはrails_helperやspec_helperを用意すれば RailsAppのRakeタスク一覧に表示され、実行も出来るようになるはず。

しかし、書き方が悪かったのかGemのテストで定義していたFactoryBotが読み込まれずエラーとなったので taskの処理を以下のように変更した。

namespace :hoge do
  task :spec do
    from_rails_helper  = "#{Hoge::Engine.root}/spec/rails_helper.rb"
    from_spec_helper = "#{Hoge::Engine.root}/spec/spec_helper.rb"
    to_dir = #{Rails.root}/spec/"
    FileUtils.mkdir_p(File.dirname(to_dir))
    FileUtils.cp(from_rails_helper, to_dir)
    FileUtils.cp(from_spec_helper, to_dir)
  end
  〜〜〜 略 〜〜〜
end

Gemで作成したrails_helperには下記のようにrequire処理を追加しておく

Dir[Rails.root.join("#{Hoge::Engine.root}/spec/factories/**/*.rb")].each {|f| require f}

凄くざっくり&強引だけど、rakeタスク実行時にrails_helperとspec_helperをGemからRailsAppへコピーして呼び出してる。 なのでRSpecのrequireは "rails_helper" だけで問題ない。

現状の課題としては

  • RailsAppからの実行なので、RailsAppのgemfileでRSpecやfactory_botがinstallされてないと実行できない。

    -> 解決した。add_development_dependencyなんてものがあった。

  • 複数のRailsEngineのテストを一気に流す事が出来ない

  • やっぱりRailsAppからではなくRailsEngine単体でテスト実行出来るようにしてCI回したい

-> add_development_dependencyオプションを使って行けるか試行錯誤中

こんなところ。

参考にさせて頂いたのは以下 qiita.com

api.rubyonrails.org