Ruby on Railsアプリケーションにおける代表的なテストフレームワークとして、RSpecがあります。 この記事では、Railsアプリケーションにおける、RSpecを中心としたテスト環境を構築する手順について解説します。

導入するGem

この記事では、以下のGemを導入する方法について解説します。 バージョン情報は、導入の際の参考にしてください。

ディレクトリ構成

この記事では、以下の各ファイルを編集していくことになります。 各ファイルについては、以降で解説します。

Gemfile
spec
├── rails_helper.rb
├── spec_helper.rb
└── support
    ├── capybara.rb
    ├── database_cleaner.rb
    ├── factory_girl.rb
    ├── shared_connection.rb
    └── shoulda_matchers.rb

1. インストールする

まず、導入するGemをインストールします。 必要なGemをGemfileに追記します。

Gemfile:

group :development do
  gem 'spring-commands-rspec'
end

group :test do
  gem 'capybara'
  gem 'capybara-email'
  gem 'database_cleaner'
  gem 'factory_girl_rails'
  gem 'poltergeist'
  gem 'rspec-rails'
  gem 'shoulda-matchers'
end

2. RSpecを初期化する

rspec-railsによる以下のコマンドで、RSpecの実行に必要な各ファイルを生成します。

$ bin/rails generate rspec:install

3. RSpecの設定をする

次に、rails_helper.rbspec_helper.rbの編集を行ないます。 通常は前者にはRails固有の設定、後者にはRSpec全般の設定を書くのですが、ここではシンプルにするためにspec_helper.rbに設定を記述します。

spec/rails_helper.rb:

require 'spec_helper'

spec/spec_helper.rb:

ENV['RAILS_ENV'] ||= 'test'

require File.expand_path('../../config/environment', __FILE__)

# Prevent database truncation if the environment is production
if Rails.env.production?
  abort('The Rails environment is running in production mode!')
end

require 'rspec/rails'

Dir[Rails.root.join('spec/support/**/*.rb')].each do |file|
  require file
end

# Checks for pending migration and applies them before tests are run
ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|
  # Mix in different behaviours to your tests based on their file location
  config.infer_spec_type_from_file_location!
end

各Gem固有の設定は、以降でspec/support/*下に記述していきます。

4. Capybaraの設定をする

Capybaraで、capybara-emailによるメールのテスト、またpoltergeistによるJavaScriptのテストを行なうために、以下の設定を行ないます。

spec/support/capybara.rb:

require 'capybara/rails'
require 'capybara/rspec'
require 'capybara/email/rspec'
require 'capybara/poltergeist'

Capybara.default_driver = :poltergeist

5. DatabaseCleanerの設定をする

database_cleanerでテストごとにデータベースを初期化するには、以下のような設定を行ないます。

spec/support/database_cleaner.rb:

RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, js: true) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end
end

6. FactoryGirlの設定をする

factory_girl_railsで以下の設定を行なうことで、FactoryGirl.createなどのメソッドのモジュール名FactoryGirlを省略することができます。

spec/support/factory_girl.rb:

RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
end

7. Shoulda Matchersの設定をする

カスタムマッチャ―としてshoulda-matchersを利用する場合は、以下の設定を行ないます。

spec/support/shoulda_matchers.rb:

Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    with.test_framework :rspec
    with.library :rails
  end
end

8. ActiveRecordの設定をする

CapybaraによるJavaScriptの非同期なテストにおいて、ActiveRecordでスレッドを共有する必要があります。 これは、以下の方法で実現できます。

spec/support/shared_connection.rb:

class ActiveRecord::Base
  mattr_accessor :shared_connection

  @@shared_connection = nil

  def self.connection
    @@shared_connection || retrieve_connection
  end
end

# Forces all threads to share the same connection. This works on Capybara
# because it starts the web server in a thread.
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection

9. Springの実行ファイルを生成する

spring-commands-rspecを用いてbin/rspecを生成すると、アプリケーションをプリロードするためRSpecの実行時間が短縮されます。 これは、以下のコマンドで生成できます。

$ bin/spring binstub rspec

おわりに

以上の設定で、基本的なテスト環境が構築できると思います。 テスト環境を構築する際はぜひ参考にしてみてください。