はじめに
今回Railsのバージョンアップに向けて不足していた箇所のテストを書いていました。
その一環で統合テストを書こうとして軽く詰まったので似たような境遇方のためになればと思い(こんなレアケースに遭遇する人は少ないと思いますが)記事にしました。
なぜ統合テストなのか
プロダクトで使用している外部サービスのAPIがjsにしか対応しておらず、プロダクト内で重要な機能の一部に組み込まれていたため。
環境
Rails 4系
Ruby 2.5.7
Rspec 3.9.1
capybara 3.30.0
対象
- すでにRspecのテスト環境が整っている。
- dockerを用いて開発を行なっている。
- dockerを用いていない場合はローカルにインストールされているブラウザを使用すれば簡単に実装できると思います。
Railsアプリケーションが入っているコンテナにchromeなどを導入する
ブラウザ用にコンテナを分けるか迷いましたが、circleciにブラウザが導入されているRubyのイメージがあったため開発環境下でもRailsアプリケーションが入っているコンテナに導入することにしました。
Dockerfileに以下のchromeやseleniumなどをインストールするためのコマンドを書き足します。
FROM ruby:2.5.7
# 下記の内容については現在の設定内容に合わせて変更してください。
# googleが用意している公開鍵をaptに追加
RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add -
# aptに安定版chromeがインストールできるレポジトリgoogle-chrome.listを追加します。
RUN echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.list
# aptで必要なパッケージをインストールします。
# seleniumをpipでインストールするため一緒にインストールします。
RUN apt-get update -qq && apt-get install -y [nodejsやRDBMSのクライアントなど] google-chrome-stable python3-pip
# seleniumでchromeを動かすためのchromedriverをダウンロードします。
# installしているchromeのバージョンに対応したchromedriverをインストールする必要があるため
# http://chromedriver.storage.googleapis.com/LATEST_RELEASE
# でchromeの安定バージョンを取得することができるため、その値を用いてchromedriverのバージョンを指定しています
RUN LATEST_RELEASE=$(curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE) &&\
wget http://chromedriver.storage.googleapis.com/$LATEST_RELEASE/chromedriver_linux64.zip
# ダウンロードしたchromedriverを解凍します。 このときPATHが通っている階層に配置しましょう。
RUN unzip chromedriver_linux64.zip -d /bin/
# pipでseleniumをインストールします。
RUN pip3 install selenium
# これより下はRailsのインストールなど既存のコードになるかと思います。
Rails側で統合テストを動かす設定
Gemfileに以下を追加
gem 'selenium-webdriver'
rails_helper.rbに以下を追加
require 'selenium-webdriver'
以下の内容を設定ファイルを作成して記述する。(rails_helper.rbなどに書いても可)
Capybara.register_driver :selenium do |app|
option = Selenium::WebDriver::Chrome::Options.new(
args: %w[--headless --disable-gpu --no-sandbox]
)
Capybara::Selenium::Driver.new(
app,
browser: :chrome,
options: option,
timeout: 600, # この設定がないとテスト内容によってはcircleciで Net::ReadTimeout となってしまう
desired_capabilities: { accept_insecure_certs: true }
)
end
Capybara.javascript_driver = :selenium
以上の設定で統合テストが実行できる環境が出来上がったと思います。
さいごに
Rails4系で統合テストのやり方を調べるとcapybara-webkitを使用した記事しか出てこなかったり、良さげなやり方を見つけてもsystem testに対応していなかったりとなにから導入していいのか調べるところからで少し詰まってしまいました。。。
また、せっかくdockerを使用しているので初めはブラウザ用のコンテナを用意しましたがコンテナ間の接続に証明書が必要でした。
証明書の発行まで書こうかと思いましたがcircleciでブラウザーが含まれたimage(今回だとcircleci/ruby:2.5.7-node-browsers)があったため分けずに構築してみました。
初めての内容ばかりだったのでおそらく改善できる点がたくさんあると思います。
改善点や気になったことがあればコメントで教えていただけると嬉しいです!
参考記事
https://qiita.com/zo30005/items/a5dcede868a3d1cca4a8
https://www.google.com/linuxrepositories/
https://www.linuxbabe.com/ubuntu/install-google-chrome-ubuntu-18-04-lts
https://circleci.com/docs/2.0/circleci-images/#language-image-variants