RailsアプリにDockerを導入した②【chromeコンテナ】

## やったこと
システムテストをコンテナ上で実行するために、chromeコンテナを起動できるように設定を行った。

## 手順
1. capybaraの設定
1. docker-compose.ymlの編集
1. 動作確認

### 1. capybaraの設定
#### spec/rails_helper.rb　コメント外す。
```rb
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }
```
#### spec/support/capybara.rbにcapybaraの設定を書く。
- Ajaxを使った部分でテスト失敗しないように、５秒待たせる
- pumaのログを出力しない
- chrome起動時のオプションの設定
    - バックグラウンドでの起動。CLIで起動する場合必須。
    - docker環境によっては、クラッシュする場合があるのでサンドボックスモード解除
    - ウィンドウサイズの指定
    - GPUハードウェアアクセラレーションを無効に。クラッシュ回避のため。
    - `dev/shm`パーティションの使用を禁止し、クラッシュ回避。
    - headlessモードでも日本語表記のHTMLが返されるよう言語指定
- コンテナ利用時に使用する、`remote_chrome`という名前でドライバを登録
    - サーバーが起動するホストのIPアドレス`server_host`、サーバーがlistenするポート番号`server_port`、そしてchromeコンテナで動作するブラウザにアクセスしてほしいURLを指定`app_host`（＝webコンテナ側のrailsアプリのURL）
- ローカルでは、`selenium_chrome_headless`ドライバを使用するよう登録
- システムテスト実行時、コンテナ上なら`remote_chrome`ドライバを、ローカル上なら`selenium_chrome_headless`を使うよう設定
```rb
Capybara.default_max_wait_time = 5
Capybara.server = :puma, { Silent: true }

options = ::Selenium::WebDriver::Chrome::Options.new
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('window-size=1680,1050')
options.add_argument('--disable-gpu')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--lang=ja-JP')

if ENV['SELENIUM_DRIVER_URL']
  Capybara.register_driver :remote_chrome do |app|
    url = ENV['SELENIUM_DRIVER_URL']
    Capybara::Selenium::Driver.new(
      app,
      browser: :remote,
      url: url,
      options: options
    )
  end
  Capybara.server_host = IPSocket.getaddress(Socket.gethostname)
  Capybara.server_port = 3001
  Capybara.app_host = "http://#{Capybara.server_host}:#{Capybara.server_port}"
else
  Capybara.register_driver :selenium_chrome_headless do |app|
    Capybara::Selenium::Driver.new(
      app,
      browser: :chrome,
      options: options
    )
  end
end

Capybara.default_driver = ENV['SELENIUM_DRIVER_URL'] ? :remote_chrome : :selenium_chrome_headless

RSpec.configure do |config|
  config.before(:each, type: :system) do
    driven_by Capybara.default_driver
  end
end
```

### 2. docker-compose.ymlの編集
docker-compose.ymlにchromeコンテナを追加
```diff_yaml
  web:
    environment:
      MYSQL_PASSWORD: password
+     SELENIUM_DRIVER_URL: http://chrome:4444/wd/hub

+ chrome:
+   image: selenium/standalone-chrome-debug:latest
+   ports:
+     - '4444:4444'
```

### 3. 動作確認
システムテストのサンプルを書き、実行してみてちゃんとcapybaraがDocker上で動いているかチェックした。

- config/routes.rbに`root to: 'samples#index'`追加
- Samplesコントローラを作成
- views/samples/index.html.erbに`Capybara疎通テスト`と記述
- spec/system/samples_spec.rbを作成し、以下のようにspecを記述し、コンテナ上でシステムテスト実行
```rb
require 'rails_helper'

RSpec.describe('Samples', type: :system) do
  describe 'Capybaraの疎通確認' do
    it 'ページが開ける' do
      visit '/'
      expect(page).to have_content 'Capybara疎通テスト'
    end
  end
end
```

## これから
chromeコンテナが正常に動いていることを確認できた :tada:
続いて、非同期ジョブの永続化のためにredisコンテナとsidekiqコンテナを作っていく。

## 参考
- [Capybara README](https://rubydoc.info/gems/capybara)
- [Capybara README 和訳](https://github.com/willnet/capybara-readme-ja)
- [Seleniumでよく使うChromeOptionsまとめ](https://boardtechlog.com/2020/08/programming/seleniumchrome%E3%81%A7%E3%82%88%E3%81%8F%E4%BD%BF%E3%81%86chromeoptions%E3%81%BE%E3%81%A8%E3%82%81/)
- [docker環境にcapybaraを導入する](https://zenn.dev/mitsuaki/articles/d2772bb8a8cd6e)
- [Rails on DockerでRSpecのSystem testをSelenium Dockerを使ってやってみた。](https://qiita.com/at-946/items/e96eaf3f91a39d180eb3)←システムテストの様子を見れる設定にしたい時に見る
- [Docker で RSpec の System Spec を実行するための設定メモ](https://qiita.com/suketa/items/d783ac61c2a3e4c16ad4)