LoginSignup
66
55

More than 3 years have passed since last update.

Rails + Selenium + DockerでSystemSpecの環境構築

Last updated at Posted at 2019-07-23

最近は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が入ってる方は、capybaraselenium-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モードで起動する

みたいなことをします。

spec/support/selenium_chrome.rb
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させることを忘れないようにしましょう。

spec/rails_helper.rb
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を指定しておけば問題ないかと思います。

これで準備が整いました。

実際にテストを走らせてみる

spec/system/**.rb
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.)

ほとんどの場合、chromeoptionに問題があります。
自分は、--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

参考記事:
https://stackoverflow.com/questions/50610316/capybara-headless-chrome-in-docker-returns-devtoolsactiveport-file-doesnt-exist

https://github.com/SeleniumHQ/selenium/issues/6088

66
55
2

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
66
55