対象者
プログラミング初学者、Ruby on Rails初学者。
こちらの記事は
・初学者の自分の知識整理
・同じような初学者向けにわかりやすく解説する
ことを目的としております。
System Specとは
Rails5.1以降で追加されたFeatureSpesに代わるテスト。
ユーザーがアプリケーションを使用する流れと同じ動作をシミュレーションして、想定通りの動きをするか確認できます。
いわゆる「E2Eテスト」「結合テスト」「システムテスト」と呼ばれるテストができます。
seleniumの設定、database cleanerが不要でありセットアップが簡単なので
FeatureSpecではなくSystemSpecを使用します。
使用する機能
今回は
テストフレームワークにRSpec
サンプルデータの生成にFactoryBot
を使用します。
FactoryBotはFixtureと違いActiveRecordを使用するため本番環境に近い状態でテストが可能になります。
その代わり動作がFixtureよりも遅くなるのでとにかく軽くしたいという場合は
fixtureをそのまま使用しても問題ありません。
手順1:gemインストール
必要なgemはrspec, factory-bot, capybara, selenium-webdriver, chromedriver-helperです。
このうちデフォルトで書かれていないrspecとfactory-botを追加します。
group :test do
gem 'rspec-rails'
gem 'factory_bot_rails'
end
bundleとrspecの設定ファイルを生成します。
$ bundle
$ rails g rspec:install
手順2:FactoryBotの準備
FactoryBotはfactoriesディレクトリ以下を参照しますので
対応するディレクトリを作成します。
また、modelに対応するファイルも用意しておきます。
$ mkdir ./spec/factories
$ touch ./spec/factories/user.rb
またmodelに対応するサンプルデータも作成します。
FactoryBot.define do
factory :user do
name {"sample"}
email {"sample@example.com"}
password { "password" }
end
end
ruby文ですがかなりスッキリした形で書くことができます。
また、ファイル名とファイル内のシンボルはモデル名に対応するように書きましょう。
手順3:SystemSpecファイルの準備
system specにはジェネレータが無いのでディレクトリとファイルを作成します。
$ mkdir ./spec/system/
$ touch ./spec/system/login_spec.rb
今回はユーザー登録の結合テストという想定にしました。
ファイルの雛形は次のような形になります。
require 'rails_helper'
RSpec.describe "User", type: :system do
it "" do
#expectations
end
end
specファイルのtypeが :system という感じですね。
ここまで来るとrspecを実行するだけで
ブラウザテストができます。
例えば
RSpec.describe "User", type: :system do
before
user = FactoryBot.create(:user)
end
it "user login" do
visit '/login'
fill_in 'email', with: user.email
fill_in 'password', with: user.password
click_button 'Sign up'
expect(page).to have_content 'login successfully'
end
end
と書けばchromeブラウザでのシミュレーションが実行されます。
手順4:設定を変更する
使いやすいうように少し設定を変更して行きます。
表示をドキュメンテーション形式に
--require spec_helper
--format documentation
headlessモードに変更
このままだと毎回chromeが起動してしまうのでテストに時間が掛かります。
その為headlessモードに変更しておきましょう。
この辺りの設定は
https://qiita.com/jnchito/items/c7e6e7abf83598a6516d
こちらに詳しく記載されています。
config.before(:each) do |example|
if example.metadata[:type] == :system
driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400]
end
end
また、systemテストに時間がかかる場合は
通常はcapybara標準のrack_testドライバを使用し、
javascriptを使う場合だけchromeを使用するという設定にします。
config.before(:each) do |example|
if example.metadata[:type] == :system
if example.metadata[:js]
driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400]
else
driven_by :rack_test
end
end
end
参考リンク
https://leanpub.com/everydayrailsrspec-jp
https://github.com/thoughtbot/factory_bot_rails
https://qiita.com/jnchito/items/c7e6e7abf83598a6516d