【Rails】『RSpec + FactoryBot + Capybara + Webdrivers』の導入&初期設定からテストの書き方まで
こんにちは、okutani(@okutani_t)です。本記事では、Ruby on Railsに『RSpec』『FactoryBot(旧FactoryGirl)』『Capybara』『Webdrivers』を導入する方法から初期設定、動作確認ていどのかんたんなテストの書き方までを解説しています。
RSpec, FactoryBot, Capybara, Webdriversのそれぞれの役割は以下のとおりです。
- RSpec:Rubyで使えるテストフレームワーク
- FactoryBot:テストデータを作成
- Capybara:フィーチャーテスト(E2Eテスト・ブラウザテストとも呼ばれる)をRubyでおこなうためのフレームワーク
- Webdrivers:ChromeDriverをかんたんに導入してくれるgem
今回使用するツールのバージョンは以下のとおりです。
- Ruby 2.6.2
- Rails 5.2.3
- RSpec 3.8.2
- FactoryBot 5.0.2
- Capybara 3.25.0
- Webdrivers 4.0.1
また、以下のテストを、かんたんなサンプルを交えて紹介しています。
- Model Spec
- System Spec
- Request Spec
今回利用しているgemのGitHubのリポジトリはこちら。
LINKrspec/rspec-rails: RSpec for Rails-3+
LINKthoughtbot/factory_bot: A library for setting up Ruby objects as test data.
LINKteamcapybara/capybara: Acceptance test framework for web applications
LINKtitusfortner/webdrivers: Keep your Selenium WebDrivers updated automatically
それでは、実際に導入方法から、テストの書き方までみていきましょう。
スポンサーリンク
もくじ
導入
プロジェクトのGemfileに以下を記述します。すでに対応するgroupが存在するかと思うので、そこにgemを追記してください。
group :development, :test do
gem 'rspec-rails'
gem 'factory_bot_rails'
end
group :test do
gem 'capybara'
# gem 'selenium-webdriver'
# gem 'chromedriver-helper'
gem 'webdrivers'
end
もしここで「chromedriver-helper」「selenium-webdriver」が記述されていたら、「Webdrivers」で代替できるので削除しましょう。
bundle installを実行。今回はプロジェクト直下に配置します。
$ bundle install --path vendor/bundle
RSpecが導入できたか確認。
$ bundle exec rspec --version
RSpec 3.8
RSpec3.8が導入されていることが確認できました。
それでは、RSpecの初期設定からおこなっていきましょう。
RSpecの初期設定
RSpecの初期設定ファイルをgenerateします。以下のコマンドを実行。
$ bundle exec rails generate rspec:install
以下のファイルが生成されます。
- .rspec
- spec/
- spec/spec_helper.rb
- spec/rails_helper.rb
ちなみに、Railsのデフォルトで配置されているtestディレクトリはもう使わないので破棄してOKです。
$ rm -rf test
もし、すでにMiniTest等でテストを書いていたらrspecに移行させてから削除しましょう。
今後は「spec/」以下にテストファイルを配置していきます。
また、今後はモデルやコントローラーを生成すると、自動でspecディレクトリにテストファイルが生成されます。
すでに作成されているモデルやコントローラーに対して、テストファイルを作成することもできます。
specファイルの自動生成設定
「config/application.rb」にrspecの設定を記述することで、rails generate時に自動生成するspecファイルを制御することができます。
module アプリ名
class Application < Rails::Application
# ...省略...
config.generators do |g|
g.test_framework :rspec,
view_specs: false,
helper_specs: false,
controller_specs: false,
routing_specs: false,
request_specs: false
end
end
end
私は上記のように設定して、viewやcontrollerなどのspecファイルは自動生成しないように設定しました。
上記は適宜お好みで設定してみてください。
出力結果を見やすくする
「.rspec」の内容を以下のようにすることで、実行結果を見やすくすることができます。
--require spec_helper
--format documentation
・before
・after
こちらもお好みで設定してみてください。
FactoryBotの初期設定
テストデータを生成するFactoryBotの初期設定をおこないます。
「spec/rails_helper.rb」に以下を追記。
RSpec.configure do |config|
# ...省略...
config.include FactoryBot::Syntax::Methods # 追加
end
これで、FactoryBotを使うときに接頭語からFactoryBotを取り除いてすっきり書くことができます。
例)
FactoryBot.create(:user)
↓
create(:user)
「FactoryBot.create(:user)」のように接頭語付きで使う場合、上記の設定は不要です。
それでは、実際にModelのテストを書いてみます。
Model Specの実装例
もし、すでにUserモデルが存在していて、specファイルが存在しない場合は以下のコマンドでテストファイルを生成します。
$ bundle exec rails g rspec:model user
今回は以下のファイルが生成されました。
- spec/models/user_spec.rb
- spec/factories/users.rb
今回はFactoryBotも同時に導入しているので、「spec/factories/users.rb」も同時に生成されました。
ちなみに、ファクトリーファイルのみを生成したい場合、以下のようにも実行できるので覚えておきましょう。
$ bundle exec rails g factory_bot:model user
生成された「spec/models/user_spec.rb」の中身は以下のとおりです。
require 'rails_helper'
RSpec.describe User, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end
「spec/factories/users.rb」の中は以下のとおり。
FactoryBot.define do
factory :user do
end
end
今回、これらのファイルを以下のように書き換えてみました。
- 「spec/models/user_spec.rb」
require 'rails_helper'
RSpec.describe User, type: :model do
it 'is valid' do
user = build(:user)
expect(user).to be_valid
end
end
- 「spec/factories/users.rb」
FactoryBot.define do
factory :user do
name { 'okutani' }
sequence(:email) { |n| "okutani#{n}@example.com" }
password { '1234abcd' }
password_confirmation { '1234abcd' }
confirmed_at { Time.current }
end
end
上記は、Devise gemで作成したUserモデルのテストデータをFactoryBotで生成し、Model Specでバリデーションのテストをおこなった例です。
実際に、Userモデルにバリデーションを追加したり外したりしてみて、挙動を確かめてみると良いですね。
では、実際にテストの実行をおこなってみます。
テスト用DBのマイグレーション
テストをおこなう前に、テスト用DBをマイグレーションしておきましょう。
以下のコマンドを実行。
$ bundle exec rails db:migrate RAILS_ENV=test
これでテスト用DBがmigrateされました。
テストの実行
以下のコマンドでテスト全体を実行できます。
$ bundle exec rails rspec spec
特定のファイルのみを実行したい場合は以下。
$ bundle exec rspec spec/models/user_spec.rb
また、次のように行数を指定することで、その行に含まれるテストのみを実行してくれます。
$ bundle exec rspec spec/models/user_spec.rb:5
これでRails + RSpecでテスト開発をおこなうことができますね。
Capybaraの初期設定
次に、System Specを利用するため、Capybaraの初期設定をおこないます。
以下のコマンドでCapybaraの設定ファイルを追加します。
$ mkdir spec/supports
$ touch spec/supports/capybara.rb
今回は「spec/supports/capybara.rb」を以下のように実装しました。
RSpec.configure do |config|
config.before(:each, type: :system) do
driven_by :selenium_chrome_headless
end
end
「spec/spec_helper.rb」に以下の行を記述し、作成した設定ファイルを読み込みます。
require 'supports/capybara'
これでSystem Specの実行時に「Headless Chrome」が利用されるようになり、テスト実行時にブラウザが立ち上がらないようになります。
System Specの実装例
Capybaraの設定が済んだので、実際にSystem Specを実装していきます(System SpecはRSpec 3.7、Rails 5.1以降で利用できます)。
以下のコマンドを実行して System Specの実行ファイルを作成。
$ mkdir spec/system
$ touch spec/system/home_spec.rb
以下のように実装してみました。
require 'rails_helper'
RSpec.feature 'Home', type: :system do
scenario 'shows greeting' do
visit root_path
expect(page).to have_content 'Hello World!'
end
end
テストを実行します。
$ bundle exec rails rspec spec
これでテストを実行し、TOPページに「Hello World!」という文字列が存在すれば、テストが成功します。
Request Specの実装例
次にRequest Specの実装例について見ていきましょう。
Rails 5.0からControllerテストは非推奨になったので、代わりにRequest Specを実装していきます。
Request Specでは以下の項目をテストします。
- リクエストに対して適切なステータスコード(200, 302など)が返ってくるか
- リターンされたビュー(もしくはJSONデータ)に想定したデータが含まれているか
- 適切にDBにデータが反映されているか
- リダイレクト処理がある場合、正しくリダイレクトされたかなど
本記事では、必要最低限動くところまでしか解説していないため、Request Specで行うべきテスト項目について詳しく知りたい場合は「rails request spec」などで調べてみてください(以下に参考になる記事を紹介しておきます)。
参考Rails5でコントローラのテストをController specからRequest specに移行する - Qiita
それでは一例として、TOPページが正しく表示されていることを確認するRequest Specを実装してみます。
以下のコマンドを実行して雛形ファイルを作成します。
$ bundle exec rails g rspec:request home
「spec/requests/homes_spec.rb」が作成されました。今回TOPページは1枚だけなので、ファイル名、ファイル内のhomesをhomeに置換して進めています。
「spec/requests/home_spec.rb」を以下のように実装しました。
require 'rails_helper'
RSpec.describe 'Home', type: :request do
describe 'GET #index' do
it 'responds successfully' do
get root_path
expect(response).to have_http_status(200)
expect(response.body).to include 'Hello World!'
end
end
end
これでhome_controllerが存在していて、かつ正しくアクセスでき、viewに「Hello World!」が含まれていればテストが成功します。
今回は、response.bodyに'Hello World!'が含まれているかどうか確認しましたが、System Specの実装例のようにhave_contentを利用してもOKです。お好みで実装してみてください。
まとめ
かんたんではありましたが、RSpecの導入&初期設定、一通りのテスト実装までを解説しました。
他にも、Helper Spec, Service Specなどを記述していけば、一通りのテストが網羅できることになりますね。
詳しいテストの実装方法については、時間があるとき別記事にまとめようと思います。
RailsでRSpecを利用する方の参考になれば幸いです。
Web開発のお仕事を募集しています
フリーランスのエンジニアとして、Webシステム開発のお仕事依頼を随時募集しています(現在の業務量によってお受けできない場合もあります)。
「Ruby on Rails」「JavaScript(jQuery, Reactなど)」「HTML + CSS」を用いたシステム開発、「Heroku」等を用いたサーバー構築・運用、「Git」や「GitHub」を利用したソーシャルコーディングなどに対応しています。
ご依頼を検討している方は、下記リンク本ブログからのお問い合わせ、もしくはokutaniのポートフォリオからご連絡ください。
LINKお問い合わせ
スポンサーリンク