Skip to content

Instantly share code, notes, and snippets.

@upinetree
Last active August 31, 2022 13:55
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save upinetree/fb71a947cc100e7918b7b280485d620c to your computer and use it in GitHub Desktop.
Save upinetree/fb71a947cc100e7918b7b280485d620c to your computer and use it in GitHub Desktop.

WSL Ubuntu 上で chromedriver を使った System Spec を動かす

エラー別トラブルシューティング

Rails デフォルトの chromedriver-helper gem をそのまま利用するだけでは、エラーが出て実行できない場合がある。

以下、エラー別に対策を考察。

エラー1: cannot find Chrome binary

背景

Rails 5.2 では、デフォルトで chromedriver-helper gem がインストールされ、以下のようにドライバとして設定される。

https://github.com/flavorjones/chromedriver-helper/blob/v2.1.0/lib/chromedriver-helper.rb#L4

ここで参照しているバイナリは、gemを実行する環境に応じて自動的にインストール&配置される。

一方、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環境にインストールする

対策A. chromedriver-helper を使わずに、自分で chromedriver を設定する

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

対策B. chromedriver-helper を利用しつつ、ChromeをWSL環境にインストールする

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

エラー2: Failed to open TCP connection to 127.0.0.1:9515

chromedriver-helper プロセスの起動に時間がかかっている説。 以下のようにするとChromeからレスポンスが帰ってくる。

$ bundle exec chromedriver-helper&
$ bundle exec rspec

Capybara::Selenium::Driver に設定する selenium-webdriver client にタイムアウト時間を設定できれば改善しそうだが、System Spec で簡単にそれができるかは未確認。

chromedriver-helper を使わずに直接 chromedriver.exe を指定したときは発生しなかったので、手っ取り早い解決にはそちらのほうが良さそう。

その他、WSLでのハマりどころ

PostgreSQL の大量のWARNING

WARNING:  could not flush dirty data: Function not implemented

下記Issueで議論されているが、未解決。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment