PIYO - Tech & Life -

Headless ChromeのテストがCircleCI上で動かなかった

CI RSpec

おとといの記事でHeadlessChromeを使ってテストするようにしたよ、と書きました。

RailsのFeatureテスト環境をHeadless Chromeに変更した - PIYO - Tech & Life -
Poltergeist detected another element ...に対応するために RailsのFeatureテスト環境をHeadless Chromeに置き換えました。 Capybara + PhantomJSのフィーチャテストでドロップダウンメニューがクリックできないので

ですが、CircleCIではこんな感じのエラーを吐いて動きませんでした。

Selenium::WebDriver::Error::SessionNotCreatedError:
        session not created exception: Chrome version must be >= 64.0.3282.0

どうやら、circleciのイメージに元々入っているchromedriverと、gemとしてインストールしているchromedriver-helperが衝突することによって起こるらしいということがわかりました。

chromedriver-helper を消す

となるとGemfileの:testのブロックからchromedriver-helperを消せばいいじゃないと思ったのですが、そうすると今度はローカルでのテストが困ります。

Macではhomebrewを使ってchromedriverをインストールすることが可能ですが、僕の場合はうまくテストから接続できず断念しました。

$ brew install chromedriver
$ brew services start chromedriver # サービスとして起動

Gemfile書き換え

さらに調べてみるとGemfileを条件付きにしてしまうという方法を見つけました。ローカルではchromedriver-helperを使うが、CircleCIでは使わないようにします。確かにこの方法を取ることができればCircleCI上でchromedriverがコンフリクトすることはありません。

Has ChromeDriver been updated on the Ubuntu 14.04 (Trusty) image?

↓このようにENV['CIRCLECI']がないときだけchromedriver-helperをインストールするようにします。

group :test do
  gem 'chromedriver-helper' unless ENV.key?('CIRCLECI')
end

また、この変更をpushしたあとはCI上のキャッシュを破棄する必要があるので「Rebuild without Cache」を実行しましょう

ある程度動くようになった、でも…

軒並み失敗していたテストのうち、ほとんどが通るようになりました。ですが、一部のテストはまたドライバー周りで失敗していそうでした。エラーは大体こんな感じです。

Failure/Error: accept_confirm { click_link '削除' }
Capybara::ModalNotFound:
 Unable to find modal dialog
 # ./spec/features/hogehoge.rb:39:in `block (5 levels) in <top (required)>'
 # ./spec/features/hogehoge.rb:38:in `block (4 levels) in <top (required)>'
 # ./spec/rails_helper.rb:106:in `block (2 levels) in <top (required)>'
 # ------------------
 # --- Caused by: ---
 # Selenium::WebDriver::Error::TimeOutError:
 #   timed out after 2 seconds (no alert open
 #     (Session info: headless chrome=61.0.3163.91)
 #     (Driver info: chromedriver=2.32.498513 (2c63aa53b2c658de596ed550eb5267ec5967b351),platform=Linux 4.4.0-116-generic x86_64))
 #   ./spec/features/hogehoge.rb:39:in `block (5 levels) in <top (required)>'

どうやら、ブラウザのconfirmダイアログを確認するところでエラーになっているようです。2秒待ったけどダイアログ出ないよ、という感じかな。

ローカルではこれらのテストはパスしているので、driverのバージョン違いがありそうです。

ちなみにchromedriveのバージョンは次の通り。

  • ローカル→2.37.544337
  • CircleCI→2.32.498513

バージョンが古いのが怪しいなと思ったのでまずはDockerイメージを変えてみることに。元々2.4系にあげるところだったのもあって、2.3.4→2.4.3とイメージを変更しました。

jobs:
  build:
    docker:
      # before
      # - image: circleci/ruby:2.3.4-node-browsers
      # after
      - image: circleci/ruby:2.4.3-node-browsers

そしたらなんかうまくいくじゃないですか。ということでイメージに入っているchromedriverのバージョンが古そうだという当たりがつきました。

ですがCIのためだけににRubyのバージョンもあげるのはプロジェクトによっては困るかもしれません。

chromedriverだけを上げる方法はないものか。CircleCIの設定ファイルでアップデートする方法を探してみます。

(Dockerのイメージを専用に作れば何にでも対応できるはずなんですが、ちょっと手間がかかりすぎるのでそこまではやめておく方針です。Dockerから調べないといけないので)

イメージを変えたらGemfileの分岐は不要に

ちなみ、イメージ変更後にGemfileのunless ENV.key?('CIRCLECI')を外して動かしたら全部通っちゃいました。

これはたまたまgemのchromedriverとDockerイメージのchromedriverが一致しているだけかもしれませんが、ひとまず不要となりました。

なんとか2.3.4のイメージで動かしたい

ローカルで試す

CircleCI 2.0からはDockerに対応しているので、わざわざCircleCIにコードをPushしなくてもローカルで動作を確認できます。DockerとCircleCI CLIを入れれば割と簡単に使えるので、設定を色々いじるときはローカルを使うのがいいです。

手順は公式のこれ。

Using the CircleCI Local CLI - CircleCI

結果は不発に

CircleCIのフォーラムとかstackexchangeとかを色々あさってChromeをアップデートする方法を色々試してみました。configを変えては$ circleci build .circleci/config.ymlを何度も走らせる。。。1回15分20分かかるので結構な時間がかかりました。

で、結局はどれもchromeがcrashするからテストできないというエラーで不発に終わりました。

unknown error: Chrome failed to start: crashed
  (Driver info: chromedriver=2.32.498513 (2c63aa53b2c658de596ed550eb5267ec5967b351),platform=Linux 4.9.87-linuxkit-aufs x86_64)

エラーを見るにchromedriverのバージョンは変わらないですね。なので実は更新ができていないんだと思われます。深追いするには利用しているDockerイメージをローカルで動かして調べてみたりするのかなー。

僕個人的には2.4.3のイメージを使えば大丈夫だったので深追いはせず一旦は諦めました。

以下、やってみてだめだったことを一応書いておきます(すべて.circleci/config.ymlに書いて試した内容です)。

参考にした情報とのセットで記載します。


https://superuser.com/questions/130260/how-to-update-google-chrome-in-ubuntu

- run:
    name: Chrome
    command: |
      wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
      sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
      sudo apt-get update
      sudo apt-get --only-upgrade install google-chrome-stable      

https://discuss.circleci.com/t/session-not-created-exception-chrome-version-must-be-62-0-3202-0/19258/8

- run:
    name: Install Chrome
    command: |
      sudo apt-get update
      sudo apt-get install google-chrome-stable      

https://discuss.circleci.com/t/session-not-created-exception-chrome-version-must-be-62-0-3202-0/19258/10

- run:
    name: Install Chrome
    command: |
      curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
      sudo dpkg -i google-chrome.deb
      sudo sed -i 's|HERE/chrome\"|HERE/chrome\" --disable-setuid-sandbox|g' /opt/google/chrome/google-chrome
      rm google-chrome.deb