Help us understand the problem. What is going on with this article?

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

最近は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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away