7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

M1 MacでRails + Docker + RSpec + CapybaraでのSystemテストの環境構築

Last updated at Posted at 2023-08-18

株式会社TECH LUCKという会社で代表兼エンジニアをしている齊藤です。

DXプロジェクト、開発プロジェクト、Rails開発などでお困りごとがありましたら弊社HPからご相談をいただけますと幸いです。
以下のような問題に対応することが可能です。

  • プロジェクトでRailsエンジニアが足りなくて困っている
  • Railsのバージョンアップをしたいがノウハウ・リソースが足りなくて困っている
  • オフショア開発をしているが、要件の齟齬やコード品質が悪いので改善したい

また、Railsエンジニアも募集しておりますので、興味がありましたら弊社HPからご連絡いただけますと幸いです。

前提

RSpecでsystemテストをする際にDockerでSeleniumを導入して、テストを実行する方法になります。

Docker関連の設定

docker-compose.yml
version: '3.7'
services:
  db:
    image: mysql:8.0
    platform: linux/x86_64
    command: --default-authentication-plugin=mysql_native_password
    ports:
      - "4306:3306"
    volumes:
      - db:/var/lib/mysql
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
    security_opt:
      - seccomp:unconfined
  webpacker:
    build: .
    volumes:
      - .:/myapp
      - bundle:/usr/local/bundle
    command: ./bin/webpack-dev-server
    environment:
      WEBPACKER_DEV_SERVER_HOST: 0.0.0.0
    ports:
      - "3035:3035"
  web:
    build: .
    stdin_open: true
    tty: true
    volumes:
      - .:/myapp
      - bundle:/usr/local/bundle
    command: bash -c "rm -rf tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    depends_on:
      - db
    ports:
      - "3000:3000"
    environment:
      WEBPACKER_DEV_SERVER_HOST: webpacker
      SELENIUM_DRIVER_URL: http://selenium_chrome:4444/wd/hub
  selenium_chrome:
    image: seleniarm/standalone-chromium
    ports:
      - "4444:4444"
volumes:
  db:
    driver: local
  bundle:
    driver: local

注意する点はselenium_chromeのイメージはselenium/standalone-chrome:latestを使っている記事が多いです。しかし、M1の場合だとこのイメージだとエラーが出てしまい動きません(これに気づくのに丸2日潰してしまった、、、。)。そのため、seleniarm/standalone-chromiumのイメージを使います。

rails_helper.rbの以下を記述します。
コメントアウトになっていますが、こちらを復活させる形で大丈夫です。

spec/rails_helper.rb
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }

spec/support/のディレクトリに、capybara.rbを作成し以下の記述をします。
これによってdocker-composeで構築されたコンテナ同士で通信してChromeが使えるようになります。

spec/support/capybara.rb
require 'capybara/rspec'
require 'selenium-webdriver'

Capybara.register_driver :remote_chrome do |app|
  url = ENV["SELENIUM_DRIVER_URL"]
  capabilities = ::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,
                                 capabilities: capabilities)
end

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

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

GitHub Actionsへの対応

CI/CDでテストを実現するために、GitHub Actionsを利用する場合の設定を書きます。
GitHub Actionsで立ち上がるコンテナにChromeをインストールして利用する形にします。

以下の記述を追加します。

.github-action.yml
- name: Chrome Install
  run: sudo apt-get install google-chrome-stable

その後、capybara.rbを変更します。

capybara.rb
require 'capybara/rspec'

Capybara.register_driver :remote_chrome do |app|
  url = ENV['SELENIUM_DRIVER_URL']
  capabilities = ::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,
                                 capabilities: capabilities)
end

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

  config.before(:each, type: :system, js: true) do
    if ENV['SELENIUM_DRIVER_URL']
      Capybara.server_host = IPSocket.getaddress(Socket.gethostname)
      Capybara.server_port = 4444
      Capybara.app_host = "http://#{Capybara.server_host}:#{Capybara.server_port}"
      driven_by :remote_chrome
    else
      driven_by :selenium_chrome_headless
    end
  end
end

これで環境変数にSELENIUM_DRIVER_URLがある場合、つまり、docker-composeで起動したrailsコンテナの中では、Dockerコンテナで立ち上がっているSelenium(remote_chrome)を使う形になります。
環境変数にSELENIUM_DRIVER_URLがない場合、つまりローカルでの開発の場合は、Github Actions内ではその環境内にインストールされているChromeを使う形になります。

参考文献

7
3
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
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?