Docker+Rails+HeadlessChromeでRSpecのSystem Testしてみた

#はじめに
今回はタイトルにある通りdockerを使用してrspecのSystem testを実行したので備忘録的に記事にしました。
こちらのrails+mysqlの環境にRSpec用の環境を加えた形になります。基本的にRSpecを追加する部分のみを記載します。
rails+mysqlの環境についてはこちらの記事をご覧ください。
[Dockerを使用した既存のRailsプロジェクトの開発環境構築（Rails+Mysql）](https://qiita.com/E6YOteYPzmFGfOD/items/7f9ec4e0f48171e351bd) 
構成としてはrailｓ＋MySQL＋test用のdb＋systemspec用に[ selenium/standalone-chrome-debug](https://hub.docker.com/r/selenium/standalone-chrome-debug)を用いた環境となります。
 

###対象読者
既存のrailsプロジェクトの開発環境にdocker＋rspecを利用したいかた。
dockerはダウンロード済みとしています。

###参考
こちらの記事を参考にさせていただいております。
[Docker で RSpec の System Spec を実行するための設定メモ](https://qiita.com/suketa/items/d783ac61c2a3e4c16ad4)
[Rails on Dockerにて、Headless ChromeでSystem Testをやってみた。](https://qiita.com/at-946/items/e96eaf3f91a39d180eb3)

###環境
Mac OS

```
docker -v
Docker version 19.03.8, build afacb8b

docker-compose -v
docker-compose version 1.25.4, build 8d51620a
```

#ファイル構成
下記のようなファイル構成にしてください。

```
testproject
└── test_app#既存プロジェクト
    ├── Dockerfile
    ├── docker-compose.yml
    ├── Gemfile
    ├── Gemfile.lock
    ├── config
    ├     └──database.yml
    ├──spec
        └──support
　　　　　　　　└──capybara.rb
```

rails用のdockerfileとdatebase.ymlの中身はこんな感じです。

```dockerfile
#既存のプロジェクトのrubyのバージョンを指定
FROM ruby:2.6.3 

#パッケージの取得
RUN apt-get update 
    && apt-get install -y --no-install-recommends\
    nodejs  \
    mariadb-client  \
    build-essential  \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*
WORKDIR /myproject

COPY Gemfile /myproject/Gemfile
COPY Gemfile.lock /myproject/Gemfile.lock

RUN gem install bundler
RUN bundle install --without production

#既存railsプロジェクトをコンテナ内にコピー
COPY . /myproject
```

```yml:datebase.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password: password

development:
  <<: *default
  host: test-db
  database: docker_test

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  host: db
  database: test_test
```

#1.docker-compose.ymlの作成

```yml:docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    ports: 
      - '3306:3306' # ホストからゲストへポートフォワード
    environment:
      MYSQL_DATABASE: docker_development
      MYSQL_ROOT_PASSWORD: password
      MYSQL_USER: root
      MYSQL_PASSWORD: password

  test-db:
      image: mysql:5.7
      ports:
        - '3307:3306' # ホストからゲストへポートフォワード
      environment:
        MYSQL_DATABASE: docker_test
        MYSQL_ROOT_PASSWORD: password
        MYSQL_USER: root
        MYSQL_PASSWORD: password
      
  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    tty: true #pry-byebugを使えるようにする
    stdin_open: true
    depends_on:
      - db # DB側のコンテナが出来上がってからwebを実行する
      - test-db
      - selenium_chrome
    ports:
      - "3000:3000" # ホストからゲストへポートフォワード
    volumes:
      - .:/myproject:cached # ソースコード変更したらDocker側も即反映されるように

  selenium_chrome:
    image: selenium/standalone-chrome-debug
    ports:
      - 4444:4444
```

selenium_chromeがchrom動作用のコンテナになります。

#2.Rspecの設定
gemファイルにrspec用のgemを追加します。

```ruby:Gem.file
group :development, :test do
  gem 'rspec-rails', '~>3.8.0'
end

group :test do
  gem 'capybara', '~> 2.15.4'
  gem 'webdrivers'
end
```
###capybaraの設定です。

```ruby:spec/rails_helper
#この一文をコメントアウト解除
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }
```

```ruby:spec/capybara.rb

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://selenium_chrome:4444/wd/hub"
  opts = { desired_capabilities: :chrome, browser: :remote, url: url }
  driver = Capybara::Selenium::Driver.new(app, opts)
end

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
```
#コンテナの立ち上げ
下記コマンドでコンテナを立ち上げて、db：migrateしてください。

```
cd test_app
#imageの作成
docker-compose build 
#コンテナの立上げ
dokcer-compose up -d
#コンテナ内で
docker-compose exec web bundle exec rails db:migrate
```
ここまできたらrspecのsystemspecのテスト（js含めて）を実行できるようになります。

```
docker-compose exec web  rspec
```
適当なファイルを作成して

```ruby:system/
RSpec.describe 'test', type: :system do
end
```

```
docker-compose exec web  rspec

Finished in 0.00105 seconds (files took 4.04 seconds to load)
0 examples, 0 failures
```
きちんとrspecが動作するのを確認できました。

###終わりに
ヘッドレスドライバーの設定がうまくいかずに、ｊｓのテストができずに悩んでいて今回この記載通りで実行できるようになったのでメモがてら記事にしてみました。最後までお読み頂きありがとうございました。