Rspec に於ける Capybara の driver 設定に関するメモ

- rails (8.0.2)
- capybara (3.40.0)
- rspec-rails (7.1.1)
- rspec-core (3.13.3)
Rspec の System spec で cuprite
を使おうと、 Capybara.javascript_driver = :cuprite
としたのだけれども、どうも :selenium
が使われている。 Rspec のテストのほうで、 describe ... type: :system, js: true do ...
といった具合に js
タグを立てれば、javascript_driver に自動で切り替わると思い込んでいた。
いろいろ迷走右往左往した結果、 System spec では javascript_driver には切り替わらない。これは Rspec の仕様のようで、ドキュメントに書いてあった。
https://rspec.info/features/7-1/rspec-rails/system-specs/system-specs/
RSpec does not use your ApplicationSystemTestCase helper. Instead it uses the default driven_by(:selenium) from Rails. If you want to override this behaviour you need to call driven_by in your specs.
デフォルトは :selenium
であるから、変えたい場合は driven_by
の設定を上書きして切り替えよ、とのこと。
(余談) ChatGPT に訊いてみました。
(問い)
https://github.com/rails/rails/issues/34379 について、どういう考えで Capybara.javascript_driver が使われないことを選択したのでしょう?
(回答)
Rails の system spec で js: true を指定しても、Capybara.javascript_driver が自動的に使用されない理由は、主に以下の技術的な背景と設計上の選択によるものです:
🧠 技術的背景と設計上の選択
- SystemTestCase の初期化タイミングと設定の適用タイミングの不一致
SystemTestCase は、driven_by(:selenium) をデフォルトで設定しています。この設定は、SystemTestCase が初期化される際に適用されます。一方で、Capybara.javascript_driver の設定は、RSpec の設定ファイル(例えば rails_helper.rb)で行われるため、SystemTestCase の初期化後に適用されます。このため、Capybara.javascript_driver の設定が SystemTestCase に反映されないという問題が発生します。
この問題を解決するためには、SystemTestCase の初期化タイミングを変更するか、Capybara.javascript_driver の設定を SystemTestCase の初期化前に行う必要があります。
- driven_by の明示的な設定の推奨
RSpec の公式ドキュメントでは、system spec でのドライバの設定は明示的に行うことが推奨されています。これは、テストの可読性と明確性を高めるためです。driven_by を明示的に設定することで、どのドライバが使用されているかが明確になり、テストの挙動を予測しやすくなります。

現在使っているドライバ設定:
Capybara.register_driver(:cuprite_custom) do |app|
# see also https://github.com/rubycdp/ferrum?tab=readme-ov-file#customization
Capybara::Cuprite::Driver.new(app,
js_errors: true,
window_size: [1200, 800],
headless: %w[0 false].exclude?(ENV['HEADLESS']),
slowmo: ENV['SLOWMO']&.to_f,
inspector: true,
browser_options: (ENV['DOCKER'] ? { 'no-sandbox' => nil } : {}).merge('accept-lang' => 'en'),
)
end
多言語化したページに対する System specs が英語表記をベースに作られていたところ、テストを実行すると軒並み FAIL になっていた。つまり cuprite が動かすブラウザがページを日本語で表示する設定になっていたことが原因である。これを英語で表示させるために browser_options
に 'accept-lang' => 'en'
を追加してみたところ、ページが英語表記になり、テストも PASS することができた。(その後、 accept-lang の値は ENV から得るようにした)
また、 ENV
を渡すアイデアは、こちらの記事 Rails: SeleniumをCupriteにアップグレードする(翻訳) の記述をそのままいただいた。
デバッグが必要になったら、怪しいコードに binding.pry
を埋め込んで、次のように実行するとよい:
$ HEADLESS=0 SLOWMO=0.5 ./bin/rspec spec/system/sample_spec.rb:123