・Docker環境でRSpecを試したらエラー発生
・解消方法とDocker環境でのRSpec導入方法を紹介
経緯
継続してRuby on Railsの学習をしています。
CRUDを用いた実装後のテストでRSpecを利用したところエラーが発生しました。
ローカル環境では動いたのでDcoker環境での追加設定が必要なため備忘も兼ねてエラー内容と解消方法、その後の実行方法の紹介となります。
Docker環境とローカル環境ではやはり色々違います。
Webサーバーとして代表的なNginxを、Docker環境で動かしてRailsアプリケーション表示させている記事も合わせてご確認ください。
環境情報
各種バージョンとライブラリは下記となります。
名前 | バージョン |
---|---|
Ruby | 2.6.3 |
Rails | 5.2.1 |
Gem名 | バージョン |
---|---|
rspec-rails | 3.9.1 |
selenium-webdriver | 3.142.7 |
webdrivers | 4.6.1 |
Gemfileの「webdrivers」ですが、最初は「chromedriver-helper」を使っていました。
ですがbundle installしたときに警告が表示されたため、「webdrivers」 を使っています。
エラー内容と所感
コマンド「rspec spec/system/tasks_spec.rb」を実行後NoMethodErrorが出力されました。
root@abf48b906977:/var/www/taskleaf# rspec spec/system/tasks_spec.rb
Capybara starting Puma...
* Version 3.12.6 , codename: Llamas in Pajamas
* Min threads: 0, max threads: 4
* Listening on tcp://127.0.0.1:39839
F
Failures:
1) タスク管理機能 一覧表示機能 ユーザーAがログインしているとき ユーザーAが作成したタスクが表示される
Got 0 failures and 2 other errors:
1.1) Failure/Error: visit login_path
Selenium::WebDriver::Error::WebDriverError:
Unable to find chromedriver. Please download the server from
https://chromedriver.storage.googleapis.com/index.html and place it somewhere on your PATH.
More info at https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver.
エラー内容はChromeDriverが無いのでダウンロードしてPATHを設定してください。と表示しているのでDocker環境にブラウザ(Chrome)が無いと思いました。
Gemfileにある selenium-webdriver や drivers はRailsでseleniumを扱うようにするライブラリです。
Nginx・Ruby・RailsのようにDocker環境で扱うツール(ブラウザ(Chrome))を用意する必要があると感じました。
解決方法
Docker hubにはseleniumで使うブラウザ(Chrome)が用意されていました。
今回はそれを利用したいと思います。
Docker-Compose.yml
docker-compose.ymlに、selenium用のコンテナ追加と、Railsアプリケーションが置いてあるコンテナ(下記コードではwebコンテナ)に環境変数を追加します。
version: "3"
services:
web:
build: ./app_rails
ports:
- "3000:3000"
environment:
- "SELENIUM_DRIVER_URL=http://selenium_chrome:4444/wd/hub"
selenium_chrome:
image: selenium/standalone-chrome-debug
logging:
driver: none
10行目以降の「selenium_chrome」がselenium用コンテナです。
webコンテナで使えるように9行目に環境変数「SELENIUM_DRIVER_URL」を追加しています。
環境変数「SELENIUM_DRIVER_URL」 の「selenium_chrome:4444」はコンテナ名に合わせます。
Railsアプリケーション
Railsアプリケーション側でも2箇所、修正と追加が必要です。
今回はrspecコマンドを動かした後で想定しています。
spec/rails_helper.rb修正
コマンド作成のままですと25行目にある下記コメントを外します。
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
spec/support/capybara.rb作成
capybara.rbを作成します。
配置箇所は上記コードに沿うようにします。spec/support配下です。
配置後下記コマンドを追加します。
require 'capybara/rspec'
RSpec.configure do |config|
config.before(:each, type: :system) do
driven_by :selenium, using: :headless_chrome, options: {
browser: :remote,
url: ENV.fetch("SELENIUM_DRIVER_URL"),
desired_capabilities: :chrome
}
Capybara.server_host = 'web'
Capybara.app_host="http://#{Capybara.server_host}"
end
end
7行目はdocker-compose.ymlで定義した環境変数を。
10行目のwebはコンテナ名を指定します。
動かした結果
以上で設定完了です。
「rspec」コマンドからテストを実行して期待通りの結果となっていることを確認します。
root@20ee950b6800:/var/www/taskleaf# rspec spec/system/tasks_spec.rb
Capybara starting Puma...
* Version 3.12.6 , codename: Llamas in Pajamas
* Min threads: 0, max threads: 4
* Listening on tcp://web:41281
.
Finished in 5.57 seconds (files took 8.68 seconds to load)
1 example, 0 failures
このとき、docker-composeのコンテナ名が「app」の場合は「ERR_SSL_PROTOCOL_ERROR」が表示されます。
「ERR_SSL_PROTOCOL_ERROR」が表示された場合はコンテナ名を見直してください。
最後に
今回は解決に至るまで複数の問題に当たり中々難儀でした。
コーディングミスもあったので正しい設定のはずがテスト失敗となり、間違った設定を試して・・・などいろんなところをグルグル回っていました。
1度成功すれば問題無いのですが、1度目の成功までが苦労します。
参考サイト
Docker で RSpec の System Spec を実行するための設定メモ
https://qiita.com/suketa/items/d783ac61c2a3e4c16ad4