Docker Selenium

はじめに

Selenium の実行時に、開発メンバーの PC 環境に依存して結果が変わってしまうことがありました。
そこで、Docker を利用して同一の環境でテストを実行できるようにしました。

PCに依存する原因:

  • 開発環境のスペックの違い
  • Chrome のバージョン差異 など

回避したかったこと

  • 「レビュー時にテストを実行するとエラーになる……。え、そっちでは失敗しないの?」
  • 「修正箇所とは関係ないところでエラーになるんだけど……。」

メリット

  • 同じバージョンのChromeDriverで実行できるため、環境差異が発生しない
  • PC リソース使用を限定できる(CPU/メモリ割り当て可能)

前提

  • Rails アプリ側はすでに Selenium が実行できる環境であること
  • 今回は既存の処理を修正し、Rails アプリはホスト PC 上で動作(http://localhost:3000)、Docker 化はしていない
  • 開発環境は MacBook Pro 2021 (Apple M1 Pro)
目次

環境情報

Seleniumコンテナ: selenium/standalone-chromium:138.0
Chromeバージョン: 138.0
Selenium Grid: <http://localhost:4444>
VNC: <http://localhost:7900>
Railsアプリケーション: <http://localhost:3000>
Railsテストアプリケーション: <http://localhost:3001>

 

使用したDocker

selenium/standalone-chromium(公式イメージ)を利用しました。
linux/amd64linux/arm64 の両方に対応しています。

構築手順

1.Seleniumコンテナの起動

# バージョン指定(138.0)でSeleniumコンテナを起動
docker run -d 
  --name selenium-chrome 
  -p 4444:4444 
  -p 7900:7900 
  --shm-size="2g" 
  --add-host=host.docker.internal:host-gateway 
 -v "$(pwd)/tmp/data/downloads:/tmp/downloads" 
  selenium/standalone-chromium:138.0
  
  # ダウンロード対応のため、ボリュームマウントの追加
  ホスト: /tmp/data/downloads
  docker: /tmp/downloads

 

 

2.Railsアプリケーションの設定

config/environments/test.rb
# これを追加しないとアクセスエラーになります
config.hosts << "host.docker.internal"

 "host.docker.internal" はDockerからホスト上のサービスにアクセスするために必要です。
今回のケースでは、RSpec 実行時にホスト側で起動している Rails アプリにアクセスするために指定しました。

この設定がないと以下のようなエラーが発生します。

[ActionDispatch::HostAuthorization::DefaultResponseApp] Blocked host: host.docker.internal

 

3.Selenium設定の修正

spec/support/capybara.rb
RSpec.configure do |config|
  config.before(:each, type: :system, selenium: true) do
    # 環境変数SELENIUM_DOCKERがtrueの場合、Docker環境で実行する
    if ENV['SELENIUM_DOCKER']
      driven_by(:selenium_remote_chrome)
    else
      driven_by(:selenium_chrome)
    end
  end
end

 

spec/spec_helper.rb
# Docker環境用のSeleniumドライバー
Capybara.register_driver :selenium_remote_chrome do |app|
  options = Selenium::WebDriver::Chrome::Options.new
  options.add_argument('--no-sandbox')
  options.add_argument('--headless')
  options.add_argument('--disable-dev-shm-usage')
  options.add_argument('--disable-gpu')
  options.add_argument('--window-size=1920,1080')

  Capybara::Selenium::Driver.new(
    app,
    browser: :remote,
    url: '<http://localhost:4444/wd/hub>',
    options: options
  )
end

# Capybara設定
Capybara.configure do |config|
  # test環境用の専用ポートを指定する3001固定
  config.server_port = 3001

  # Docker環境用のapp_host設定
  config.app_host = 'http://host.docker.internal:3001' if ENV['SELENIUM_DOCKER']
end

 

4.テスト実行

# 全テスト実行
SELENIUM_DOCKER=true bundle exec rspec spec/system/hogehoge_spec.rb --tag selenium

 

Seleniumが動作しているところが見たい

1.VNCのパスワード無効にして、docker起動

docker run -d --name selenium-chrome -p 4444:4444 -p 7900:7900 --shm-size="2g" --add-host=host.docker.internal:host-gateway -e SE_VNC_NO_PASSWORD=1 selenium/standalone-chromium:138.0

2.ブラウザで http://localhost:7900 を開く

3.「Connect」をクリック

4. headlessモードを無効

spec/spec_helper.rb
# Docker環境用のSeleniumドライバー
Capybara.register_driver :selenium_remote_chrome do |app|
  options = Selenium::WebDriver::Chrome::Options.new
  options.add_argument('--no-sandbox')
#  options.add_argument('--headless') ←コメントアウト

 5.テスト実行 

残課題

  • ファイル選択周り

 

おまけコマンド

# 既存のコンテナを停止・削除
docker stop selenium-chrome && docker rm selenium-chrome

# コンテナの状態確認
docker ps

# コンテナの停止・削除
docker stop selenium-chrome && docker rm selenium-chrome

# コンテナのログ確認
docker logs selenium-chrome

# イメージの確認
docker images selenium/standalone-chromium

# コンテナログ確認
docker logs selenium-chrome

# Railsアプリケーション確認
curl -I <http://localhost:3000>

# Selenium Grid状態確認
curl -s <http://localhost:4444/status> | jq .

 

 

役に立ったらシェアしていただけると嬉しいです
  • URLをコピーしました!
  • URLをコピーしました!
目次