最近はDockerでRails環境を構築する方も多いかと思い、system specができるように環境構築を記事にしてみました。
たった5文字のミスで2週間以上ハマるという泣きたくなる体験もしたので、今後同じ道を辿らないよう遭遇したエラーログたちも残しておきます。
##開発環境
・Rails 5.1.7
・Ruby:2.3.7 (🙇♂️)
・RSpec 3.8
・ChromeDriver 75.0.3770.90
・google-chrome-stable 75.0.3770.100
・capybara (3.15.1)
・DockerImage
##Gemfile
すでにrspec-rails
が入ってる方は、capybara
とselenium-webdriver
を追加します。
gem 'rails', '~> 5.1.0'
...
...
group :development, :test do
gem "rspec-rails"
end
group :test do
gem 'capybara'
gem 'selenium-webdriver'
end
selenium-webdriver
を利用することで、ブラウザを自動で操作してテストができるようになります。
注意点としては、最新版を使わないとchrome
とのバージョンと互換性がとれなくなる可能性があるので、常に最新バージョンに保つようにすべきです。
bundle update capybara selenium-webdriver
##Dockerfile
DockerImageはこちらを元にしてます。
ここでは、最新バージョンのchromedriver
と、google-chrome-stable
をインストールしていきましょう。
FROM ruby:2.3.7
ENV LANG C.UTF-8
RUN apt-get update -qq && apt-get install -y build-essential node.js
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
&& apt-get install -y nodejs
# chromeの追加
RUN apt-get update && apt-get install -y unzip && \
CHROME_DRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE` && \
wget -N http://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip -P ~/ && \
unzip ~/chromedriver_linux64.zip -d ~/ && \
rm ~/chromedriver_linux64.zip && \
chown root:root ~/chromedriver && \
chmod 755 ~/chromedriver && \
mv ~/chromedriver /usr/bin/chromedriver && \
sh -c 'wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -' && \
sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list' && \
apt-get update && apt-get install -y google-chrome-stable
RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY . /app
CMD ["rails", "server", "-b", "0.0.0.0"]
chromedriver
の配布されてるバージョンはこちらから確認できます。
記事執筆時点での最新バージョンは75.0.3770.140
でした。
コンテナに入って確認する場合↓
chromedriver -v
=> ChromeDriver 75.0.3770.140 (2d9f97485c7b07dc18a74666574f19176731995c-refs/branch-heads/3770@{#1155})
google-chrome-stable --version
=> Google Chrome 75.0.3770.100
##Rspecの設定
・Capybaraにドライバを登録
・Seleniumのoptionを指定する
・js使いたいときだけheadlessモードで起動する
みたいなことをします。
require 'capybara/rspec'
require 'selenium-webdriver'
Capybara.register_driver :selenium_chrome_headless do |app|
options = ::Selenium::WebDriver::Chrome::Options.new
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--window-size=1400,1400')
driver = Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end
Capybara.javascript_driver = :selenium_chrome_headless
sprc/support
以下をincludeさせることを忘れないようにしましょう。
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
RSpec.configure do |config|
config.before(:each, type: :system) do
driven_by :rack_test
end
config.before(:each, type: :system, js: true) do
driven_by :selenium_chrome_headless
end
end
注意点としては、**オプションに--no-sandbox
を指定することです。**これがないと正常に動作しません。
また、使用できるドライバは:selenium
, :selenium_headless
, :selenium_chrome
, :selenium_chrome_headless
の4つあり非常にややこしいのですが、:selenium_chrome_headless
を指定しておけば問題ないかと思います。
これで準備が整いました。
##実際にテストを走らせてみる
require "rails_helper"
RSpec.describe 'Ideas', type: :system, js: true do
let(:user) { create(:user, name: "hoge") }
subject { visit root_path }
it "ユーザー一覧表示" do
subject
expect(page).to have_content("hoge")
end
end
1 example, 0 failures
ちゃんと通りました。
##苦戦したエラーたち
##Selenium::WebDriver::Error::UnknownError
Selenium::WebDriver::Error::UnknownError:
unknown error: Chrome failed to start: exited abnormally
(unknown error: DevToolsActivePort file doesn't exist)
(The process started from chrome location /usr/bin/chromium is no longer running, so ChromeDriver is assuming that Chrome has crashed.)
ほとんどの場合、chrome
のoption
に問題があります。
自分は、--no-sandbox
をつけ忘れてこのエラーを吐いていました。
必要なオプションについてはこちらを参考にしてみると良いかもしれません。
##Failed to read the 'sessionStorage' property from 'Window': Storage is disabled inside 'data:' URLs
sessionStorage
を読み込めませんよ!というエラー。
Selenium::WebDriver::Error::WebDriverError:
<unknown>: Failed to read the 'sessionStorage' property from 'Window': Storage is disabled inside 'data:' URLs.
(Session info: headless chrome=75.0.3770.100)
しかし、capybara
でこのエラーを出す猛者はほぼ一人もあわられず、調べてもAnguler
のテストフレームワークであるProtractor
の記事しか出ません。
https://stackoverflow.com/questions/24205856/protractor-empty-local-storage
個人的な原因としては、pathにアクセスできていなかったというもの。
SystemSpec側でvisit
をつけ忘れるという。。
subject { root_path }
→ subject { visit root_path }
としたことで無事解決しました。
OSSまで読んだのに、まさかここだとは思わず1週間以上取られて泣きたい。
動くまでの格闘記を以下に貼っておきます。
https://teratail.com/questions/200250#reply-296669