【Rails6】Docker環境でRSpecのシステムスペックを実行する

# はじめに

こちらの記事の続きとなります。

[【Rails6】Docker + Rails + MariaDB のローカル環境でアプリ開発を始めよう【おとなもこどもも、おねーさんも】](https://qiita.com/masarashi/items/61c5d9c63e9588b948f0)

Dockerコンテナで使用する Rubyイメージですが、システムスペックを実行する際に必要なブラウザがインストールされておらず、システムスペックを実行できません。
ブラウザをインストールしてしまうという方法もありますが、システムスペックは開発環境で実行し、本番環境では実行しないためブラウザが不要です。
何かをインストールすれば少なからずイメージ容量が増えてしまう点や、開発環境だけブラウザがインストールされるように Dockerファイルを作るのもメンテナンス性の観点から避けたいです。

そこで、ブラウザを別のコンテナとして起動することで解決します。


# RSpecの設定

RSpecの設定に関しては、「Everyday Rails - RSpecによるRailsテスト入門」を参考にさせていただきました。

追加インストールした Gemは下記です。（該当部分のみ抜粋。）

```ruby:Gemfile
group :development, :test do
  gem 'factory_bot_rails'
  gem 'rspec-rails'
end

group :development do
  gem 'spring-commands-rspec'
end

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

なお、はじめは`selenium-webdriver`の代わりに`webdrivers`という Gemを使っていました。

参考
[サポートが終了したchromedriver-helperからwebdrivers gemに移行する手順](https://qiita.com/jnchito/items/f9c3be449fd164176efa)

しかし、webdriversではうまくいかず、試行錯誤の末、上記のとおり`selenium-webdriver`を使うことで解決しました。


# 参考にさせていただいた記事

[Rails on DockerでRSpecのSystem testをSelenium Dockerを使ってやってみた。](https://qiita.com/at-946/items/e96eaf3f91a39d180eb3)


# 設定方法

### Chromeコンテナの設定

解決のため、Chromeを別のコンテナで稼働させます。

`docker-compose.yml`に追記します。（該当部分のみ記載）

```yml:docker-compose.yml

  app:
    environment:
      SELENIUM_REMOTE_URL: http://chrome:4444/wd/hub
    depends_on:
      - chrome

  chrome:
    image: selenium/standalone-chrome:latest
    ports:
      - 4444:4444
```


### RSpecの設定

```ruby:rails_helper.rb

①コメントを外す
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }

RSpec.configure do |config|

②追記
+  config.include Devise::Test::IntegrationHelpers, type: :system
end
```

```ruby:capybara.rb

RSpec.configure do |config|
  config.before(:each, type: :system) do
    driven_by :remote_chrome
    Capybara.server_host = IPSocket.getaddress(Socket.gethostname)
    Capybara.server_port = 3000
    Capybara.app_host = "http://#{Capybara.server_host}:#{Capybara.server_port}"
  end

  config.before(:each, type: :system, js: true) do
    driven_by :remote_chrome
    Capybara.server_host = IPSocket.getaddress(Socket.gethostname)
    Capybara.server_port = 3000
    Capybara.app_host = "http://#{Capybara.server_host}:#{Capybara.server_port}"
  end
end

# Chrome
Capybara.register_driver :remote_chrome do |app|
  url = 'http://chrome:4444/wd/hub'
  caps = ::Selenium::WebDriver::Remote::Capabilities.chrome(
    'goog:chromeOptions' => {
      'args' => [
        'no-sandbox',
        'headless',
        'disable-gpu',
        'window-size=1680,1050'
      ]
    }
  )
  Capybara::Selenium::Driver.new(app, browser: :remote, url: url, desired_capabilities: caps)
end
```

# コンテナの停止

```terminal
docker-compose down
```

稼働中のコンテナがないことを確認します。

```terminal
docker-compose ps

Name   Command   State   Ports
------------------------------
```

# イメージのビルドとコンテナの起動（同時に）

```terminal
docker-compose up —build
```

# 解消

`docker-compose ps`で Chromeのコンテナが起動しているか確認します。

```terminal
             Name                            Command               State                 Ports               
-------------------------------------------------------------------------------------------------------------
　・
　・
sample_app_chrome_1               /opt/bin/entry_point.sh          Up      0.0.0.0:4444->4444/tcp
```

これにてシステムスペックが実行出来るようになりました！