既存のrailsアプリをdocker化するとローカルでエラーなく走っていたRSpec
のsystem spec
のテストが何一つまともに走ってくれず、修正した内容の備忘録となります。
どなたかのお力になれば嬉しいです。
プログラミング初学者なので、内容に誤り等ある可能性があります
誤りがありましたら教えてくださると幸いです
環境
ruby 3.2.2
Ruby on Rails 7.0.8
Docker 24.0.2
エラーその1
docker compose run web bundle exec rspec
を実行すると
1.1) Failure/Error: visit root_path
Selenium::WebDriver::Error::WebDriverError:
unable to connect to /root/.cache/selenium/chromedriver/linux64/122.0.6261.57/chromedriver 127.0.0.1:9515
解決のためにしたこと
Gemfileからwebdriverの記述をコメントアウト
group :test do
gem 'capybara'
gem 'selenium-webdriver'
# gem 'webdrivers'
end
docker上でテストを行う際は、Seleniumの公式Dockerイメージであるseleniarm/standalone-chromium
を使用します。このイメージにはブラウザとそれに対応するwebdriverがすでに含まれているためwebdrivers
を使用する必要はありません。
ブラウザが動作するためのコンテナを作成
web:
#省略
depends_on:
- db
- selenium_chrome
selenium_chrome:
image: seleniarm/standalone-chromium
ports:
- 4444:4444
selenium_chrome
コンテナを追加
私はM1 Macを利用しているためimage
にはseleniarm/standalone-chromium
を使用しています
https://qiita.com/mejiro03/items/76f7080b3ab25cbee8e4
https://qiita.com/se_yataro/items/4a741658495cf43df552
capybara.rbを作成
Capybara
の設定をカスタマイズするためspec/support/capybara.rb
を作成
RSpec.configure do |config|
config.before(:each, type: :system) do
driven_by :remote_chrome
Capybara.server_host = IPSocket.getaddress(Socket.gethostname)
Capybara.server_port = 4444
Capybara.app_host = "http://#{Capybara.server_host}:#{Capybara.server_port}"
end
config.before(:each, type: :system, js: true) do
driven_by :remote_chrome
Capybara.server_host = IPSocket.getaddress(Socket.gethostname)
Capybara.server_port = 4444
Capybara.app_host = "http://#{Capybara.server_host}:#{Capybara.server_port}"
end
end
# Chrome
Capybara.register_driver :remote_chrome do |app|
url = ENV['SELENIUM_DRIVER_URL']
options = ::Selenium::WebDriver::Chrome::Options.new
options.add_argument('no-sandbox')
options.add_argument('headless')
options.add_argument('disable-gpu')
options.add_argument('window-size=1680,1050')
Capybara::Selenium::Driver.new(app, browser: :remote, url: url, options: options)
rail_helper.rbの修正
# デフォルトでコメントアウトされているので、コメントを外す
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
これを外すことでreqire "rails_helper"
とテストファイル(hoge_spec.rb
)に記述したときspec/support
配下のファイルが自動的に読み込まれます。
エラーその2
Failure/Error: avatar.variant(resize_to_fit: [400, 400]).processed
LoadError:
Could not open library 'vips.so.42': vips.so.42: cannot open shared object file: No such file or directory.
Could not open library 'libvips.so.42': libvips.so.42: cannot open shared object file: No such file or directory.
Searched in <system library path>, /usr/lib, /usr/local/lib, /opt/local/lib
解決のためにしたこと
docker環境にvipsのインストール
gemimage_processing
を使用していましたが、docker環境にもvipsをインストールしなければならない
Dockerfile
に以下の記述を追加して再度docker compose up --build
を実行
RUN apt-get update -qq && apt-get install -y --no-install-recommends libvips42
エラーその3
hoge_spec.rb
でcapybaraのusing_session
を使用して2つのセッションを用いてテストコードを書いていたら起きたエラー
2.3) Failure/Error: Unable to infer file and line number from backtrace
Selenium::WebDriver::Error::InvalidSessionIdError:
invalid session id
2.4) Failure/Error: Unable to infer file and line number from backtrace
Selenium::WebDriver::Error::InvalidSessionIdError:
invalid session id
解決のためにしたこと
selenium_chromeコンテナのセッション上限数を拡張
こちらの記事に書かれている通り公式にデフォルトでは、SE_NODE_MAX_SESSIONS 環境変数によって、コンテナごとに 1 つのセッションのみが実行されるように設定されている。
と記述されている
そのためdocker-compose.yml
ファイルを以下のように修正した
selenium_chrome:
image: seleniarm/standalone-chromium
environment:
- SE_NODE_MAX_SESSIONS=2 #有効なセッション数を2つに拡張
- SE_NODE_OVERRIDE_MAX_SESSIONS=true #オーバーライドの設定を有効に
ports:
- 4444:4444
エラーその4
エラーその3が無事解決し、using_session
を使用したテストコードも無事に成功したので、hoge_spec.rb
に記述している全てのテストをまとめて走らせたら起きたエラー
Selenium::WebDriver::Error::UnknownError:
unknown error: session deleted because of page crash
from unknown error: cannot determine loading status
from tab crashed
(Session info: chrome-headless-shell=121.0.6167.160)
1.2) Failure/Error: Unable to infer file and line number from backtrace
Selenium::WebDriver::Error::InvalidSessionIdError:
invalid session id
解決のためにしたこと
Dockerコンテナに割り当てるリソース量を増やす
selenium_chromeコンテナのメモリのリソース量を拡張
selenium_chrome:
image: seleniarm/standalone-chromium
shm_size: 256m #メモリ不足を解消
environment:
- SE_NODE_MAX_SESSIONS=2
- SE_NODE_OVERRIDE_MAX_SESSIONS=true
ports:
- 4444:4444```dockerfile:docker-compose.yml
参考記事
https://peno022.hatenablog.com/entry/docker-rails7-rspec-configuration-for-system-spec
https://nekonenene.hatenablog.com/entry/selenium-3-to-4-system-spec-net-read-timeout
https://zenn.dev/mitsuaki/articles/d2772bb8a8cd6e
https://zenn.dev/felmy/articles/0f534f8f7bee49