レガシーに半身浴しているような、ふだんなかなか触らないけれど現役のレポジトリに潜んでいた亡霊を退治!!! Poltergeist + PhantomJS を消し去り、 Selenium + Headless Chromium に置き換えた。
このレポジトリは Rails による API バックエンドと SPA フロントエンド両方を管理しているもので、以下の2箇所で PhantomJS に依存していた。
- Capybara による feature spec。PhantomJS の driver として poltergeist を使用。
- Teaspoon による frontend の JavaScript test。Teaspoon は JS のテストランナーでもあり PhantomJS driver も内包している 。
両方について書いたら思いの外長くなってしまったのでこの記事では 1. の方のリプレイスについてのみ書く。後半の 2. の方は PhantomJS + Poltergeist を Selenium + Headless Chrome で置き換える (2) Teaspoon による JavaScript test 編 - valid,invalid で。
動機
PhantomJS は元々ベースにしている Webkit が古くて最新のブラウザで利用可能な JS, CSS を充分サポートできていなかったのに加え、Chrome 59 の headless mode リリース以降コアメンテナが離れたことでプロジェクトの将来性が危ぶまれる。
PhantomJS が依存している Qt のインストールでしょっちゅう問題が起きる。
結果、可及的速やかにリプレイスすることが望ましい状況だと思いました。(というか、全部リプレイス済だとなぜか勝手に思ってた)
変更内容について
このリプレイスは同僚が既に他のレポジトリで実践していた内容をほとんど拝借した。とはいえ自分で pull request を送るのだからきちんと理解したいと思い Selenium webdriver の Ruby binding 実装を少し読んでみたりもした。
実際のコード差分
Gemfile は少しスッキリ。開発環境では Docker compose を使い、アプリケーションとは別の Docker コンテナ上で立ち上げている selenium/standalone-chrome
に接続しているので今回は chromedriver や chromedriver-helper gem のインストールはしていない。
# Gemfile group :test do gem 'capybara' - gem 'capybara-webkit' - gem 'phantomjs', :require => 'phantomjs/poltergeist' - gem 'poltergeist' + gem 'selenium-webdriver' end
capybara.rb
の設定方法はぐぐると諸々出てくるので今なら悩みどころは多くなさそうだ。
Headless Capybara Feature Specs with Chrome RSpec の feature spec でヘッドレス Chrome を使う - Speee DEVELOPER BLOG
など。
# spec/support/capybara.rb - require 'capybara/poltergeist' - require 'phantomjs' + require 'capybara/rspec' + require 'selenium-webdriver' - Capybara.javascript_driver = :poltergeist + Capybara.javascript_driver = :selenium - Capybara.register_driver(:poltergeist) do |app| + Capybara.register_driver :selenium do |app| - options = { } # 省略 + options = { + browser: :chrome, + desired_capabilities: Selenium::WebDriver::Remote::Capabilities.chrome( + chrome_options: { + args: %w(headless window-size=1680,1050), + } + ) + } + options.merge!(url: ENV['SELENIUM_URL']) if ENV['SELENIUM_URL'].present? - Capybara::Poltergeist::Driver.new(app, options) + Capybara::Selenium::Driver.new(app, options) # その他 remote で Selenium を動かすための設定が続くがリプレイスとあまり関係ないので省略 end
実際はアプリケーション固有の設定などもあってもう少し複雑になったがだいたいこのような感じ。
Selenium の URL を環境変数で渡せることで local でも remote でも実行できるようになっている(はず)。
ちなみにサンプルによく出てくる disable-gpu
フラグは Google Developers ガイドにも載っているので広まったのだと思うが、現時点で最新の Chrome 65 では不要になっている。Chrome 63で動いたという報告も見かけた。(ただし Windows では動くかわからない)
737678 - Headless: make --disable-gpu flag unnecessary - chromium - Monorail
Selenium なんとなく設定周りが複雑でとっつきづらい印象があったのだが wiki は丁寧に書かれている上にコードも思ったほど入り組んでいなかった。
どうやら自分の敬遠は Selenium をラップしてる各々のライブラリの統一感の無さとかから来ているのかもしれない…。