rspec-rails
は、単体ではGeneratorのspecをサポートしていません。そこで、ammeter
というGemを使用して、Generatorのテストを書くことが出来ます。このammeter
は、RSpec自身の内部でGeneratorのテストのために使用されています。
ammeter
RSpec内部のGeneratorテスト
セットアップ
Gemfile
group :test do
gem 'rspec-rails'
gem 'ammeter'
end
spec/spec_helper.rb
require 'rspec/rails'
require 'ammeter/init'
テスト
例として、以下のようにinitializerとlocaleファイルを生成するintall generatorを自作のGem (my_gem) に実装したとします。
lib/generators/my_gem/install_generator.rb
require 'rails/generators/base'
require 'securerandom'
module MyGem
module Generators #:nodoc:
class InstallGenerator < Rails::Generators::Base
source_root File.expand_path("../../templates", __FILE__)
desc "Creates a MyGem initializer and copy locale files to your application."
# Copies initializer file in application directory
def copy_initializer
template "my_gem.rb", "config/initializers/my_gem.rb"
end
# Copies locale files in application directory
def copy_locale
template "locales/en.yml", "config/locales/my_gem.en.yml"
end
# Shows readme to console
def show_readme
readme "README" if behavior == :invoke
end
end
end
end
このGeneratorに対して、RSpecで以下のようにテストを書くことが出来ます。
spec/generators/install_generator_spec.rb
require 'generators/my_gem/install_generator'
describe MyGem::Generators::InstallGenerator, type: :generator do
# Generatorによって生成されるファイルの一時的な置場所を指定します
destination File.expand_path("../../../tmp", __FILE__)
before { prepare_destination }
# 実行時に期待するメソッドが呼び出されているかをテストします
it 'runs both the initializer and locale tasks' do
gen = generator
expect(gen).to receive :copy_initializer
expect(gen).to receive :copy_locale
expect(gen).to receive(:readme).and_return(true)
gen.invoke_all
end
describe 'the generated files' do
# 各ファイルが期待されたとおりに生成されているかをテストします
before do
# beforeブロックの中でGeneratorを起動します
run_generator
end
# 生成されたinitializerをテストします
describe 'the initializer' do
# 生成された場所とファイル名をテストします
subject { file('config/initializers/my_gem.rb') }
it { is_expected.to exist }
# ファイルの中身をテストします
# 正規表現の中身は、テンプレートに合わせて変更して下さい
it { is_expected.to contain(/MyGem.configure do |config|/) }
end
# 生成されたlocaleファイルをテストします
describe 'the locale file' do
# 生成された場所とファイル名をテストします
subject { file('config/locales/my_gem.en.yml') }
it { is_expected.to exist }
# 正規表現の中身は、テンプレートに合わせて変更して下さい
it { is_expected.to contain(/en:\n/) }
end
end
end
テスト内容はコメントの通りです。
Generatorの実装によってテストの内容は変更します。Generatorがオプション引数を取る場合には、contextブロックを定義して、run_generator
に以下のようにオプションを渡すと便利です。
spec/generators/install_generator_spec.rb
context 'with a locale option as jp' do
before do
# オプションを渡してGeneratorを起動します
run_generator %w(--locale jp)
end
# 同様にテストを記述します
end