#はじめに
Docer環境でRSpecのSystem Specを導入しようとしたところ、結構ハマったので、備忘録としてまとめます。
まず、Docer環境にSystem Specを実行するためには、いくつか方法があるらしい。
調査をしていると、メジャーな方法は以下の二つ(もっとあるかもしれませんが、、、)
1. Railsが動いているimageにchromeをインストールする方法
2. chrome用コンテナを立ち上げる方法
今回は2の方法でやってみました。
#前提
Quickstart: Compose and Railsの通りに、Rails on Dockerの環境構築が済んでいる状態とします。
筆者の環境は
- Ruby 2.5.7
- Rails 5.2.4
です。
#docker-compose.ymlを編集する
selenium_chromeのコンテナが立ち上がるようdocker-compose.ymlに追加していきます。
Dockerイメージにはselenium/standalone-chromeを使用します。
version: '3'
services:
db:
image: postgres
volumes:
- ./tmp/db:/var/lib/postgresql/data
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
#追加
- chrome
#追加
chrome:
image: selenium/standalone-chrome:3.141.59-dubnium
ports:
- 4444:4444
#gemを追加する
group :development, :test do
gem 'rspec-rails'
end
group :test do
gem 'capybara', '>= 2.15'
gem 'selenium-webdriver'
end
dockerをbuildして、bundle installします。
$ docker-compose build
$ docker-compose up -d
#rspecの設定
rspecをインストールします。
$ docker-compose run web rails g rspec:install
#headless chromeの設定
spec/rails_helper.rbにheadless chromeの設定を追加していきます。
require 'capybara/rspec'
# headless chrome 設定①
Capybara.server_host = Socket.ip_address_list.detect { |addr| addr.ipv4_private? }.ip_address
Capybara.server_port = 3001 ※
Capybara.register_driver :selenium_remote do |app|
url = "http://chrome:4444/wd/hub"
opts = { desired_capabilities: :chrome, browser: :remote, url: url }
Capybara::Selenium::Driver.new(app, opts)
end
# headless chrome 設定②
RSpec.configure do |config|
config.before(:each, type: :system) do
driven_by :rack_test
end
config.before(:each, type: :system, js: true) do
driven_by :selenium_remote
host! "http://#{Capybara.server_host}:#{Capybara.server_port}"
end
end
ポイント:
後半部分(# headless chrome 設定②)で、
js: true
を記述した場合のみ、seleniumドライバーが立ち上がるように設定しています。
ハマったポイント:
js: true
のテストを走らせたとき、Capybaraがseleniumサーバーを立ち上げて、先ほど設定したchromeコンテナで起動しているchromeを操作します。
しかし、Capybara.server_portを指定する部分(*)で、webコンテナで指定したポートと同じ3000を指定してしまうと、js: true
のテストを走らせたときに、webコンテナで指定したポートと競合してseleniumサーバーが立ち上がらずエラーとなってしまいます。
そこで、Capybara.server_port = 3000 3001
とすることで、競合することなく、無事サーバーが立ち上がり、テストが通るようになりました。
これで準備は整いました。
あとは、テストを実際に走らせるだけです。
#実際にテストを走らせてみる
require "rails_helper"
RSpec.describe 'Test', type: :system, js: true do
example 'サンプルテスト' do
#ここにテスト内容を記述
end
end
$ docker-compose exec web bundle exec rpsec
これで、テストが通るはずです。
##参考記事
下記の記事を参考にさせていただきました。
ありがとうございます。