はじめに
seleniumを実行時に開発メンバーごとのPCに依存して結果が変わってし舞うことがあった。
Docker使って同じ環境でテスト実施したかった。
PCに依存する原因:
・開発環境のスペックの違い
・chromeのバージョン違い
etc
回避したかったこと
・レビュー時にテスト実行するとエラーになるんだけど?え?そっちは失敗しない??
・テスト実行したら修正箇所と関係ないとこでエラーになったんだけど…
メリット
・同じバージョン(chrome driver)で実施するので、環境差異が生まれない
・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
https://hub.docker.com/r/selenium/standalone-chromium
selenium公式の環境。linux/amd64, linux/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 \
selenium/standalone-chromium:138.0
2.Railsアプリケーションの設定
# config/environments/test.rbに追加
config.hosts << "host.docker.internal"
これを追加しないとアクセスエラーになります
[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
if ENV['SELENIUM_DOCKER']
# Docker環境用のSelenium設定
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
# Docker環境用のCapybara設定
Capybara.configure do |config|
# test環境用の専用ポート
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が動作しているとこが見たい
- 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 .