4
2

More than 3 years have passed since last update.

Docker + Rails 環境にSystem Specを導入する

Posted at

いろいろ調査しながら対応したのでまとめておきます :pencil:

環境

rails (6.0.1)
rspec-rails (3.8.2)
capybara (3.29.0)
docker 2.1.0.5 (40693)

手順

gemのインストール

まずはSystem Specに必要なgemをインストールします。

Gemfile
group :test do
  gem 'capybara'
  gem 'selenium-webdriver'
end

もちろん、Rails環境がDockerで動いている場合はコンテナ内で実行する必要があります。

# サービス名がappの場合
$ docker-compose run --rm app bundle install

Docker用スクリプト作成

System Specに必要なchromeをどう用意するかですが、

  1. chromeをrails環境と一緒のイメージでbuildする
  2. chrome用コンテナをdocker-composeに追加する
  3. chrome用コンテナをdockerコマンドで立ち上げる

などなど、いろいろ方法があって、今回は「既存のコンテナに変更を加えなくて良い」という理由で3にしました。
そして、いちいちdockerコマンドを叩くのも面倒なのでスクリプトを作りました。
spec実行時にchromeのdockerコンテナを起動して、spec終了時にコンテナも終了させています。

なお、Dockerイメージにはselenium/standalone-chromeを使っています。
SeleniumHQ/docker-selenium

bin/system_spec
#!/bin/sh

docker run -itd --rm --net=your_app_default --name chrome -p 4444:4444 selenium/standalone-chrome

if [ $# -eq 0 ]; then
  docker-compose run --rm app rspec spec/system
else
  docker-compose run --rm app rspec $*
fi

docker stop chrome

ちなみに--netのネットワーク名はディレクトリ名_defaultとなるので注意してください。
詳しくはreferenceを参照してください。
- Docker run リファレンス — Docker-docs-ja 17.06.Beta ドキュメント
- Compose のネットワーク機能 — Docker-docs-ja 17.06.Beta ドキュメント

以下のように実行します。

# すべてのsystem_specを実行
$ bin/system_spec

# 一部のsystem_specを実行
$ bin/system_spec spec/system/users_spec.rb

System Spec

gemもコンテナも用意できたので、specを書いていきます。

driverでのremote設定、app_host設定あたりがポイントです。

spec/support/capybara.rb
# frozen_string_literal: true

require 'capybara/rspec'

Capybara.register_driver :headless_chrome do |app|
  capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
    chromeOptions: {
      args: %w[--headless --no-sandbox --disable--gpu --window-size=1280x800]
    }
  )
  opts = { desired_capabilities: capabilities, browser: :remote, url: 'http://chrome:4444/wd/hub' }
  Capybara::Selenium::Driver.new(app, opts)
end

Capybara.server_host = '0.0.0.0'
Capybara.javascript_driver = :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 :headless_chrome
    Capybara.app_host = "http://#{Socket.gethostname}"
  end
end

あとはこんなかんじでspecを書いていけばOKです。

spec/system/users_spec.rb
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe 'Users', type: :system, js: true do
  describe 'ユーザー一覧' do
    subject(:visit_page) { visit '/users' }

    it do
      visit_page
      expect(page).to have_current_path '/users'
    end
  end
end

以上です :hugging:

参考

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2