🎃

Playwright の無駄づかい

2021/08/31に公開
2

2021年8月現在、Ruby on Rails で使い捨て可能な E2E テスト環境をより手軽に手に入れる方法をまとめます。

概要

次の環境で Playwright server/client (not official feature) によるブラウザ操作を実現します。
この記事の目標は、簡単なフォーム操作をエンドツーエンドテストすることとします [1]
ただし、試験的な機能を使用しているため組み合わせなどで動作しなくなることがあります。

名称 Version Docker Image
Ruby 3.0.2 ruby:3.0.2-bullseye
Ruby on Rails 6.1.4.1
Playwright 1.14.1 mcr.microsoft.com/playwright:v1.14.1-focal
Turnip 4.3.0
Playwright client for Ruby 1.14
Playwright driver for Capybara 0.1.5

扱わないこと

試していないので、次のような設定や比較は扱いません。

したごしらえ

E2E テスト対象は scaffold で生成した Blog システムを使用します。コンテナ内のソースコードには Visual Studio Code Remote - Containers などでアクセスしてください。

Docker

docker-compose.yml
version: "3.8"

services:
  rails:
    restart: "no"
    image: rails:6.1.4
    tty: true
    environment:
      - TZ=Asia/Tokyo
      - RAILS_LOG_TO_STDOUT=true
      - RAILS_SERVE_STATIC_FILES=true
    ports:
      - "3000:3000"
    build:
      context: .
      dockerfile: Dockerfile.rails
      args:
        RUBY_VERSION: "3.0.2"
        PLAYWRIGHT_VERSION: "1.14.1"

  playwright:
    restart: "no"
    image: playwright:1.14.1
    build:
      context: .
      dockerfile: Dockerfile.playwright
      args:
        PLAYWRIGHT_VERSION: "1.14.1"
Dockerfile.rails
ARG RUBY_VERSION
FROM ruby:${RUBY_VERSION}-bullseye

# See: https://github.com/nodesource/distributions
RUN set -eux; \
  apt-get update; \
  curl -fsSL https://deb.nodesource.com/setup_14.x | bash -; \
  apt-get install -y --no-install-recommends \
    \
    nodejs \
  ; \
  rm -rf /var/lib/apt/lists/*

# See: https://github.com/microsoft/playwright
RUN PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm install --global playwright@${PLAYWRIGHT_VERSION}

# See: https://railsguides.jp/getting_started.html
RUN gem install rails -v 6.1.4.1; \
  rails new /opt/blog --database=sqlite3 -M -C -J -T --skip-webpack-install

WORKDIR /opt/blog

RUN rails db:create; \
  rails generate scaffold Article title:string body:text; \
  rails db:migrate

EXPOSE 3000
CMD [ "rails", "server", "--binding=0.0.0.0", "--port=3000" ]

Dockerfile.playwright
# See: https://playwright-ruby-client.vercel.app/docs/article/guides/playwright_on_alpine_linux#server-code
ARG PLAYWRIGHT_VERSION
FROM mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-focal

WORKDIR /root
RUN npm install playwright@${PLAYWRIGHT_VERSION} && ./node_modules/.bin/playwright install

# TODO: 必要であればフォントなどをインストールしてください。

EXPOSE 4545
CMD ["./node_modules/.bin/playwright", "run-server", "4545"]

正確ではありませんが、コンテナは下図のような関係になります。

Turnip などの設定

RSpec 経由で E2E を実行する最低限の設定をします。

Gemfile
group :test do
  gem 'rspec', '~> 3.10'
  gem 'rspec-rails', '~> 5.0', '>= 5.0.2'
  gem 'turnip', '~> 4.0', '>= 4.0.1'
  gem 'playwright-ruby-client', '~> 1.14'
  gem 'capybara-playwright-driver', '~> 0.1.5'
end
.rspec
--require test_helper
--require turnip/rspec
spec/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?

require 'capybara/rspec'
require 'capybara_helper'
Dir.glob("spec/steps/**/*step.rb") { |f| load f, true }
config/environments/development.rb
# Backend host エラーの回避
config.hosts << 'rails'

Playwright client for Ruby + Playwright driver for Capybara

起動するブラウザを変えるには browser_type を変更すればよいはずです。

spec/capybara_helper.rb
require 'capybara-playwright-driver'

# Note: 最小限の変更にしたいので Playwright.create を Playwright.connect_to_playwright_server に置き換える
# See: https://github.com/YusukeIwaki/playwright-ruby-client/blob/1.14.0/lib/playwright.rb
# See: https://github.com/YusukeIwaki/capybara-playwright-driver/blob/0.1.5/lib/capybara/playwright/driver.rb#L46-L48
module CapybaraPlaywrightDriverPatch
  private def playwright_execution
    @playwright_execution ||= ::Playwright.connect_to_playwright_server('ws://playwright:4545/ws')
  end
end
Capybara::Playwright::Driver.prepend(CapybaraPlaywrightDriverPatch)

# See: https://github.com/YusukeIwaki/capybara-playwright-driver
Capybara.register_driver(:playwright) do |app|
  driver = Capybara::Playwright::Driver.new(app, browser_type: :firefox, headless: true,
    viewport: { width: 480, height: 360 })
  driver.on_save_screenrecord do |video_path|
    # video_path: playwright container 内のパス
  end

  driver
end

Capybara.default_max_wait_time = 5
Capybara.default_driver = :playwright
Capybara.save_path = 'tmp/capybara'

Capybara.configure do |config|
  config.default_driver = :playwright
  config.javascript_driver = :playwright
end
Capybara.app_host = 'http://rails:3000'

テストコードの実行

実行したときの WebM を Gif に変換したもの↓

demo

脚注
  1. フォーム操作だけであれば Playwright である必要はありませんので、無駄づかいと言えるでしょう(タイトル回収ノルマ達成)。 ↩︎

Discussion

ピン留めされたアイテム
Yusuke IwakiYusuke Iwaki

そのGemの作者です。ご紹介&興味深い無駄遣いありがとうございます。
たしかにdocker-composeだとリモート接続になるので、Capybaraドライバにもそのオプションが必要そうですね。
次のバージョンで対応しようと思います。https://github.com/YusukeIwaki/capybara-playwright-driver/pull/44
https://rubygems.org/gems/capybara-playwright-driver/versions/0.1.6 で対応しました。

Capybara.register_driver(:playwright) do |app|
  driver = Capybara::Playwright::Driver.new(app,
    playwright_server_endpoint_url: 'ws://playwright:4545/ws', # ←これを追加
    browser_type: :firefox,
    headless: true,
    viewport: { width: 480, height: 360 })
  driver.on_save_screenrecord do |video_path|
    # video_path: playwright container 内のパス
  end

  driver
end

(ドキュメントも近々更新します)

maeda-mmaeda-m

コメントだけでなく Capybaraドライバ側のオプション対応までもいただけるとは。
大変ありがとうございます。

※僭越ながら記事の先頭にコメントへのリンクを追加させてもらいました。