Abstract
以前、Rails on Dockerでdocker-seleniumを利用してSelenium+RSpec+Capybaraのテストを実行する方法をメモしてました。
--> Rails on Dockerにて、Headless ChromeでSystem Testをやってみた。 - Qiita
System testは記事でもメモった通り色々と便利。
ただ、Railsアプリケーションが動くコンテナ内でテストを完結することができたのでそちらのメモを残します。
コンテナのベースは以下のRails on Docker(alpine linux)で。
--> Rails on DockerのQuickstartをalpine linuxでやってみる - Qiita
環境準備
環境準備として、Dockerfile
とdocker-compose.yml
をいじっていきます。
FROM ruby:2.6.5-alpine3.10
ENV RUNTIME_PACKAGES="linux-headers libxml2-dev make gcc libc-dev nodejs tzdata postgresql-dev postgresql yarn vim" \
CHROME_PACKAGES="chromium-chromedriver zlib-dev chromium xvfb wait4ports xorg-server dbus ttf-freefont mesa-dri-swrast udev" \
BUILD_PACKAGES="build-base curl-dev" \
ROOT="/myapp" \
LANG=C.UTF-8 \
TZ=Asia/Tokyo
WORKDIR ${ROOT}
COPY Gemfile ${ROOT}
COPY Gemfile.lock ${ROOT}
RUN apk update && \
apk upgrade && \
apk add --no-cache ${RUNTIME_PACKAGES} && \
apk add --no-cache ${CHROME_PACKAGES} && \
apk add --virtual build-packages --no-cache ${BUILD_PACKAGES} && \
bundle install && \
apk del build-packages
COPY . ${ROOT}
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
Dockerfileについては、CHROME_PACKAGES
のインストールを追加しています。CHROME_PACKAGES
がこのコンテナ内でChromeブラウザを立ち上げるためのパッケージたちです。
version: '3'
services:
db:
image: postgres:12.0-alpine
volumes:
- ./tmp/db:/var/lib/postgresql/data
environment:
- TZ=Asia/Tokyo
web:
build: .
command: ash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
environment:
- RAILS_SYSTEM_TESTING_SCREENSHOT=inline
web
コンテナがRailsアプリケーションが実行されるコンテナですが、環境変数としてRAILS_SYSTEM_TESTING_SCREENSHOT=inline
を追加しています。macのiTerms2を利用している場合は、これを設定しておくとRSpecのSystem TestでNGがあったときにスクリーンショットがiTerm2で表示されるようになるので便利です。
RSpecのインストール
Gemfileにrspec-railsを追加します。
group :test do
gem 'rspec-rails', '~>3.8'
gem 'capybara', '>= 2.15'
gem 'selenium-webdriver'
end
一度リビルドしてRSpecをインストールしていきます。
$ docker-compose build
$ docker-compose run --rm web rails g rspec:install
RSpecの環境設定
Headless Chromeをデフォルトのドライバーに設定します。rails_helper.rb
に以下を追加します。
Capybara.register_driver :selenium_chrome_headless do |app|
options = ::Selenium::WebDriver::Chrome::Options.new
options.add_argument('--no-sandbox')
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--window-size=1680,1050')
Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end
RSpec.configure do |config|
config.before(:each, type: :system) do
driven_by :selenium_chrome_headless
end
end
rails_helper
をデフォルトで読み込むように設定しておきます。
--require rails_helper
System Testを書いてみる
まずはtestコードの格納する場所を作っていきます。
$ mkdir spec/system
ではテストコードを書いていきます。type
をsystem
に指定することでRSpecのSystemテストとして実行させれます。
feature "sample", type: :system do
scenario "sample" do
visit root_path
expect(current_path).to eq root_path
end
end
ファイル名に_spec
とつけているのはポイントです。デフォルトで、_spec
と名付けられているファイルをテストファイルとしてRSpecが判断してテストを実行してくれます。
このテストコードだと、ルートパスにアクセスして、ルートパスにたどり着けたことを検証してます。
$ docker-compose run --rm web rspec
Capybara starting Puma...
* Version 3.12.1 , codename: Llamas in Pajamas
* Min threads: 0, max threads: 4
* Listening on tcp://127.0.0.1:44815
.
Finished in 15.43 seconds (files took 12.21 seconds to load)
1 example, 0 failures
成功しましたか?
ちょっとトラブルシューティング。
ChildProcess::LaunchError:
No such file or directory - /root/.webdrivers/chromedriver
RSpec実行時にこんなエラーが出ました。Gemfileのwebdrivers
を削除すると改善されました。おそらくchromedriverのpathがwebdrivers
の影響で異なってしまったのが原因かと思います。webdrivers
はrails new
のときに-T
オプションをつけていない場合デフォルトで導入されるので要チェックです。
Testを失敗させてスクリーンショットをみてみる
試しにテストを失敗させてみます。
feature "sample", type: :system do
scenario "sample" do
visit root_path
expect(current_path).to eq new_user_path
end
end
$ docker-compose run --rm web rspec
お、失敗しましたね。
テストが失敗するのはいいんですが、なにやらscreenshotが真っ白...
Rails6.0.0 + RSpec3.8だとこういうことが起きちゃうらしいですね。
Rails アプリケーションの不安定なテストを撲滅したい 〜system spec のデバッグ方法とテストを不安定にさせる要因〜 - あらびき日記 を参考にhelperを作っていきます。
まず、rails_helper.rb
でテストサポート用のファイルの場所を定義している箇所があるのでコメントアウトをはずします。
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
これで、spec/support/**/*.rb
のファイルがテスト実行時に呼び出されるようになりました。ので、そこにhelperファイルを作っていきます。
$ mkdir -p spec/support/helpers
$ touch spec/support/helpers/visible_screenshot_helper.rb
module VisibleScreenshotHelper extend ActiveSupport::Concern
included do |example_group|
example_group.after do
take_failed_screenshot
end
end
def take_failed_screenshot
return if @is_failed_screenshot_taken
super
@is_failed_screenshot_taken = true
end
end
RSpec.configure do |config|
config.include VisibleScreenshotHelper, type: :system
end
完成です。もう一度RSpecを実行してみましょう。次はscreenshotがちゃんと表示されるはずです。
Conclusion
Rails on DockerのQuickstartをalpine linuxでやってみる - Qiita の記事からテスト自動化の追加設定ができました。screenshotはどっかのバージョンで対応されるのかなー。