Rails デフォルトの chromedriver-helper gem をそのまま利用するだけでは、エラーが出て実行できない場合がある。
以下、エラー別に対策を考察。
Rails 5.2 では、デフォルトで chromedriver-helper
gem がインストールされ、以下のようにドライバとして設定される。
https://github.com/flavorjones/chromedriver-helper/blob/v2.1.0/lib/chromedriver-helper.rb#L4
ここで参照しているバイナリは、gemを実行する環境に応じて自動的にインストール&配置される。
- https://github.com/flavorjones/chromedriver-helper/blob/v2.1.0/lib/chromedriver/helper.rb#L63
- https://github.com/flavorjones/chromedriver-helper/blob/v2.1.0/lib/chromedriver/helper.rb#L71-L75
一方、WSL上では、環境は linux-gnu と判定されるため、インストールされる chromedriver はLinux用。
$ ruby -e "p RbConfig::CONFIG['host_os']"
"linux-gnu
ChromeがインストールされているのはWSLの外のWindows環境。 なのでパスが通っていないし、バイナリも不一致となってしまう。
そのため cannot find Chrome binary
のようなエラーが出るなどして System Spec を実行できない。
以下の2種類の対策方法がありそうだ。
- A. chromedriver-helper を使わずに、自分で chromedriver を設定する
- B. chromedriver-helper を利用しつつ、ChromeをWSL環境にインストールする
chromedriver-helper を Gemfile から削除。
- gem 'chromedriver-helper'
chromedriver.exe を直接ダウンロード。
http://chromedriver.chromium.org/downloads
適当なところへ配置。今回は C:\Program Files\chromedriver_win32\chromedriver.exe
とした。
パスを Selenium Webdriver に教えてあげる。
# spec/spec_helper.rb
require 'selenium-webdriver'
Selenium::WebDriver::Chrome.driver_path = "/mnt/c/Program Files/chromedriver_win32/chromedriver.exe"
これで設定はOK。
次のような Task リソースとテストがあったとして
# routes.rb
Rails.application.routes.draw do
root 'tasks#index'
resources :tasks
end
# spec/system/root_spec.rb
require 'rails_helper'
describe 'Hello, world', type: :system do
it 'shoud show tasks' do
Task.create!(name: 'hello')
Task.create!(name: 'world')
visit root_path
expect(page).to have_content 'hello'
expect(page).to have_content 'world'
end
end
無事成功!
$ bundle exec rspec spec/system/root_spec.rb
Capybara starting Puma...
* Version 3.12.0 , codename: Llamas in Pajamas
* Min threads: 0, max threads: 4
* Listening on tcp://127.0.0.1:49817
DevTools listening on ws://127.0.0.1:49823/devtools/browser/f55109a7-1159-43cb-aa4e-c15a6d91b052
.
Finished in 2.78 seconds (files took 2.71 seconds to load)
1 example, 0 failures
WSL Ubuntu に Chrome をインストール。(参考: https://askubuntu.com/a/196100 )
$ wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
$ sudo sh -c 'echo "deb https://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
$ sudo apt-get update
$ sudo apt-get install google-chrome-stable
テスト実行時に以下のエラーが発生する場合。
Selenium::WebDriver::Error::UnknownError:
unknown error: Chrome failed to start: crashed
(unknown error: DevToolsActivePort file doesn't exist)
(The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.)
(Driver info: chromedriver=73.0.3683.20 (8e2b610813e167eee3619ac4ce6e42e3ec622017),platform=Linux 4.4.0-17763-Microsoft x86_64)
Selenium の Chrome の起動オプションに --no-sandbox
を加える。
(参考:
https://stackoverflow.com/questions/50642308/org-openqa-selenium-webdriverexception-unknown-error-devtoolsactiveport-file-d
)
config.before(:each, type: :system) do
- driven_by :selenium_chrome_headless
+ caps = Selenium::WebDriver::Remote::Capabilities.chrome("chromeOptions" => {
+ "args" => %w(--headless --disable-gpu --no-sandbox)
+ })
+ driven_by :selenium, using: :chrome, options: { desired_capabilities: caps }
end
Chrome に渡すオプションを変更するために、上記は冗長な表記になっている。
Rails 6 ではもうちょっと簡単にできるようになりそう?
https://github.com/rails/rails/commit/01a26e581f977b08de072ce3c40b9adee2ba1c10
chromedriver-helper プロセスの起動に時間がかかっている説。 以下のようにするとChromeからレスポンスが帰ってくる。
$ bundle exec chromedriver-helper&
$ bundle exec rspec
Capybara::Selenium::Driver
に設定する selenium-webdriver client にタイムアウト時間を設定できれば改善しそうだが、System Spec で簡単にそれができるかは未確認。
chromedriver-helper を使わずに直接 chromedriver.exe を指定したときは発生しなかったので、手っ取り早い解決にはそちらのほうが良さそう。
WARNING: could not flush dirty data: Function not implemented
下記Issueで議論されているが、未解決。