コンテナで Rails の System Test を完結させる


なにこれ


Docker Compose で Rails 6.0 を動かそうと思って、いろいろネット上で情報を探した結果、ついに Docker 環境で System Test を完結できたので、ここに報告させていただく。

コード

Dockerfile

FROM ruby:2.7.0-alpine as base

WORKDIR /usr/src/app

COPY Gemfile Gemfile.lock yarn.lock package.json ./

RUN     apk update && apk upgrade && \
    apk add --no-cache build-base tzdata libxml2-dev curl yarn imagemagick postgresql-client postgresql-dev && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    gem update --system && bundle install && \
    yarn install && yarn upgrade && yarn cache clean && \
    rm -rf /usr/local/bundle/cache/* /usr/local/share/.cache/* /var/cache/* /tmp/* && \
    apk del build-base libxml2-dev curl


From base as development_test
RUN     mkdir /var/cache/apk && \
    apk update && apk upgrade && \
    apk add --no-cache build-base git chromium-chromedriver chromium zlib-dev xvfb wait4ports xorg-server dbus ttf-freefont mesa-dri-swrast udev curl && \
    apk del build-base

From base as prodution
RUN cp /usr/share/zoneinfo/UTC /etc/localtime && \
    apk del tzdata

Docker compose File

version: '3.7'

volumes:
  pg_data:
  redis_data:
  vendor_cache:
  rails_tmp_data:

networks:
  main:
    driver: bridge

services:
  relational_database:
    image: postgres:11-alpine
    ports:
      - 54321:5432
    environment:
      DATABASE_HOST: relational_database
      POSTGRES_DB: data
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    networks:
      main:

  key_value_store:
    networks:
      main:
    image: redis:4.0
    environment:
      TZ: Asia/Tokyo
    ports:
      - 6379:6379
    volumes:
      - redis_data:/var/lib/redis
    networks:
      main:

  application_server:
    build:
      context: ./rails
      dockerfile: Dockerfile
      target: prodution
    ports:
      - 3333:3000
    volumes:
      - ./rails/:/usr/src/app/
      - rails_tmp_data:/usr/src/app/tmp/
      - vendor_cache:/usr/src/app/vendor
    stdin_open: true
    tty: true
    environment:
      - DATABASE_HOST="relational_database"
      - DATABASE_PORT=5432
      - DATABASE_USERNAME='user'
      - DATABASE_PASSWORD='pass'
      - REDIS_URL='redis://key_value_store:6379'
    command: 
      /bin/sh -c "yarn install --check-files && bundle update && rails db:drop && rails db:create && rails db:migrate && rm -f /usr/src/app/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0' --early-hints"
    links:
      - key_value_store
      - relational_database
    networks:
      main:

application_system_test_case.rb

require 'test_helper'

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400], options: { args: ["headless", "disable-gpu", "no-sandbox", "disable-dev-shm-usage"] }
end

users_test.rb

require "application_system_test_case"

class UsersTest < ApplicationSystemTestCase
  setup do
    @user = users(:one)
  end

  test "visiting the index" do
    visit users_url
    assert_selector "h1", text: "Users"
  end  
end

Gemfile

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.7.0'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.2', '>= 6.0.2.1'
# Use postgresql as the database for Active Record
gem 'pg', '~> 1.2', '>= 1.2.2'
# Use Puma as the app server
gem 'puma', '~> 4.3', '>= 4.3.2'

group :test do
  gem 'capybara', '>= 2.15'
  gem 'minitest-reporters', '~> 1.4', '>= 1.4.2'
  gem 'selenium-webdriver'
end

gem 'tzinfo-data'

おわりに

今まで Ubuntu で System Test、それ以外は Alpine on Docker という環境でシステムテストをやっていたので、なんのためのコンテナ技術だよ、って感じだった。そんなストレスも明日からはすべて解決されると思えば、この苦労もやるだけの価値があったような気がする。

参考文献