LoginSignup
5
4

More than 5 years have passed since last update.

RSpecでGeneratorのテストを書く

Last updated at Posted at 2016-09-22

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
5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4