30
33

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-06-29

前回の記事、
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
30
33
0

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
30
33