Ruby
Chrome
Selenium
Capybara
Docker

CapybaraからHeadless Chromeを動かす環境をDockerで構築する

前回の記事、

Dockerを使ってHeadless Chromeを動かしてみるでDockerからHeadless Chromeを使う環境が出来たので、これをベースにCapybaraからHeadless Chromeを使う環境を構築してみます。


Docker Imageの構築

前回からの変更点としては、chromium-chromedriverの追加とRuby関連のライブラリの追加です。nokogiri等も入れてbunlde install時に

困らないようにしておきます。

FROM alpine:edge

RUN apk add --update \
udev \
ttf-freefont \
chromium \
chromium-chromedriver

RUN mkdir /noto

ADD https://noto-website.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip /noto

WORKDIR /noto

RUN unzip NotoSansCJKjp-hinted.zip && \
mkdir -p /usr/share/fonts/noto && \
cp *.otf /usr/share/fonts/noto && \
chmod 644 -R /usr/share/fonts/noto/ && \
fc-cache -fv

WORKDIR /
RUN rm -rf /noto

RUN apk add --update ruby \
ruby-bundler \
ruby-irb \
ruby-dev \
build-base \
libxml2-dev \
libxslt-dev \
libffi-dev \
zlib-dev
RUN gem install nokogiri --no-doc --no-ri
RUN gem install ffi --no-doc --no-ri

ENTRYPOINT tail -f /dev/null


Capybaraのインストール

前段落で構築したイメージをコンテナを起動して、Capybaraをインストールします。

下記のようなGemfileを作成してbundle installを行います。

# frozen_string_literal: true

source "https://rubygems.org"

gem "rspec"
gem "json"
gem "capybara"
gem "selenium-webdriver"


Capybaraの設定

ここはseleniumを使うときと大きな違いはありませんが、

webdriverからchromeに渡すオプションにheadlessで必要な

項目を渡します。


spec_helper.rb

require 'capybara/rspec'

require 'selenium-webdriver'

RSpec.configure do |config|
config.include Capybara::DSL
end

base_args = %w{headless no-sandbox disable-gpu}
Capybara.register_driver :headless_chromium do |app|
args = base_args.dup << "--window-size=1900,1080"
caps = Selenium::WebDriver::Remote::Capabilities.chrome(
"chromeOptions" => {
'binary' => "/usr/bin/chromium-browser",
'args' => args
}
)
driver = Capybara::Selenium::Driver.new(
app,
browser: :chrome,
desired_capabilities: caps
)
end
Capybara.default_driver = :headless_chromium


chomeOptionsのbinaryのところには、Headless Chomeのバイナリ

のパスを指定します。今回の環境では/usr/bin/chrominm-browserが

Headless Chomeのパスになっていました。


Capybaraを使ったテストの実行

ここは通常のCapybara+Seleniumの時の処理を同じように

記述します。


my_spec.rb

Capybara.app_host = 'http://qiita.com/'

describe "http://qiita.com" do

before do
visit '/'
end

it "we can see top page" do
expect(page).to have_content('Qiitaは、プログラマのための
技術情報共有サービスです。'
)
expect(page.driver.browser.current_url).to match /qiita/
page.save_screenshot('screenshot.png')
end
end


ただし、[2017/6最新]RubyとSeleniumでHeadless chromeを動かす on Ubuntu/Linuxにあるとの同じエラーは当然発生するためにCapybaraでも以下のような

コードはエラーになってしまいます。


fill_in.rb

Capybara.app_host = 'http://qiita.com/'

describe "http://qiita.com" do

before do
visit '/'
end

it "input identity" do
fill_in('identity', :with => "dd511805")
expect(page.driver.browser.current_url).to match /qiita/
end
end


javascriptでのキー入力はできるようなので、この場合では

fill_inとは別の関数(下の例ではfill_in_val)を定義しておいて、

テストを書き換えることで、エラーを回避しつつ、テストが

実行できます。


fill_in.rb

module HeadlessAction

def fill_in_val(id, options)
with = options.delete(:with)
page.execute_script "document.getElementById(\"#{id}\").value = \"#{with}\";"
end
end

RSpec.configure do |config|
config.include HeadlessAction
end
Capybara.app_host = 'http://qiita.com/'

describe "http://qiita.com" do

before do
visit '/'
end

it "input identity" do
fill_in_val('identity', :with => "dd511805")
expect(page.driver.browser.current_url).to match /qiita/
end
end