Pappeteerを用いたカピバラなしのレールアプリケーションのためのシステム試験
Refer this article instead if you can read Japanese sentences.
日本語を読める方はこちらの記事を見てください
背景
Railsは「システムテスト」を導入しました.これはカピバラの設定を容易にします.我々はしばしば“受け入れテスト”のためだけではなく、Rails/Vueや他のリッチJavascriptの機能を備えたRailsアプリケーションのUIテストのために使用することがあります.
カピバラDSLは、実際にはJavaScriptの豊富な機能を持つページで動作するための少し不正確です.
カピバラは、間隔10 msecで内部的にポーリングして、利用可能な要素と操作可能なものを待ちます.
https://github.com/teamcapybara/capybara/blob/0468de5a810aae75ab9de20447e246c5c35473f0/lib/capybara/node/base.rb#L91
私は、これが本当に主要な原因であるということを知りません、しかし、我々はしばしばカピバラを使っているフレーク/不安定なテストケースに直面するかもしれません.
一方、Puppeteer or Playwright 要素を待機させるための再利用可能なソリューションがあります.
Page#waitForSelector
and Page#waitForNavigation
. (脚本家はより高度な機能を持っているauto-waiting )私は実際にRailsアプリケーションでそれらを使用するためのライブラリを移植しました.
カピバラがいない場合はどうなりますか?
カピバラは巨大なフレームワークなので、カピバラなしで何が起こるかを想像するのは難しいでしょう.
実際にカピバラなしのRailsアプリケーション機能を失う
visit
またはその他のメソッドが発生するNoMethodError
の代わりにtype: :feature
type: :system
例えば、メタデータfeature
background
scenario
機能仕様カピバラなしでHTTPサーバーの起動テスト
カピバラは本当に優しい
http://127.0.0.1:3000
カピバラの論理を参照するpreparing server and launching Puma server , 次に、以下のようにテストサーバーを起動するための最小限の設定を簡単に見つけることができます.RSpec.configure do |config|
config.before(:suite) do
# launching Rails server for system testing
require 'rack/builder'
testapp = Rack::Builder.app(Rails.application) do
map '/__ping' do # debugging endpoint for heartbeat
run ->(env) { [200, { 'Content-Type' => 'text/plain' }, ['OK']] }
end
end
require 'rack/handler/puma'
server_thread = Thread.new do
Rack::Handler::Puma.run(testapp,
Host: '127.0.0.1',
Port: 3000,
Threads: '0:4',
workers: 0,
daemonize: false,
)
end
# Waiting for Rails server is ready, using Net::HTTP
require 'net/http'
require 'timeout'
Timeout.timeout(3) do
loop do
puts Net::HTTP.get(URI("http://127.0.0.1:3000/__ping"))
break
rescue Errno::EADDRNOTAVAIL
sleep 1
rescue Errno::ECONNREFUSED
sleep 0.1
end
end
end
# Configure puppeteer-ruby for automation
config.around(type: :feature) do |example|
Puppeteer.launch(channel: :chrome, headless: false) do |browser|
@server_base_url = 'http://127.0.0.1:3000'
@puppeteer_page = browser.new_page
example.run
end
end
end
この設定をspec/support/integrationCount TestHandヘルパーに入れます.RBまたはあなたが好む別の場所は、今私たちは以下のような人形劇でシステムのテストを楽しむことができます!既に述べたように、システムスペック仕様のSpec Spec(RSpec Railsによって提供される)を使用することはできません.
require 'rails_helper'
describe 'example' do
let(:base_url) { @server_base_url }
let(:page) { @puppeteer_page }
let(:user) { FactoryBot.create(:user) }
it 'can browse' do
page.goto("#{base_url}/tests/#{user.id}")
page.wait_for_selector('input', visible: true)
page.type_text('input', 'hoge')
page.keyboard.press('Enter')
text = page.eval_on_selector('#content', 'el => el.textContent')
expect(text).to include('hoge')
expect(text).to include(user.name)
end
end
生産用の小さなリファクタリング
前のセクションで紹介されたテストサーバーを起動するロジックは、本当に簡単です.しかし、ほとんどのユーザーは、それがあまりに汚いので、それをあなた自身の製品にコピー/ペーストすることを躊躇します
いいえ心配は、ここでより多くのコードをより良いコードです
Rack::Server.start
HTTPサーバを起動するにはthe implementation of rackup
command class RackTestServer
def initialize(app:, **options)
@options = options
@options[:Host] ||= '127.0.0.1'
@options[:Port] ||= 3000
require 'rack/builder'
@options[:app] = Rack::Builder.app(app) do
map '/__ping' do
run ->(env) { [200, { 'Content-Type' => 'text/plain' }, ['OK']] }
end
end
end
def base_url
"http://#{@options[:Host]}:#{@options[:Port]}"
end
def start
require 'rack/server'
Rack::Server.start(**@options)
end
def ready?
require 'net/http'
begin
Net::HTTP.get(URI("#{base_url}/__ping"))
true
rescue Errno::EADDRNOTAVAIL
false
rescue Errno::ECONNREFUSED
false
end
end
def wait_for_ready(timeout: 3)
require 'timeout'
Timeout.timeout(3) do
sleep 0.1 until ready?
end
end
end
このテストサーバでは、rspec設定ファイルは非常に短く簡単になります.RSpec.configure do |config|
config.before(:suite) do
# Launch Rails application
test_server = RackTestServer.new(
# options for Rack::Server
# https://github.com/rack/rack/blob/2.2.3/lib/rack/server.rb#L173
app: Rails.application,
server: :puma,
Host: '127.0.0.1',
Port: 3000,
daemonize: false,
# options for Rack::Handler::Puma
# https://github.com/puma/puma/blob/v5.4.0/lib/rack/handler/puma.rb#L84
Threads: '0:4',
workers: 0,
)
Thread.new { test_server.start }
test_server.wait_for_ready
end
# Configure puppeteer-ruby for automation
config.around(type: :feature) do |example|
Puppeteer.launch(channel: :chrome, headless: false) do |browser|
@server_base_url = 'http://127.0.0.1:3000'
@puppeteer_page = browser.new_page
example.run
end
end
end
さて、テストのためにhttpサーバを起動したい場合は、アプリケーションからカピバラを取り除くことができます.また、使用することができますrack-test_server あなた自身のracktestserverを定義する代わりに宝石.
Reference
この問題について(Pappeteerを用いたカピバラなしのレールアプリケーションのためのシステム試験), 我々は、より多くの情報をここで見つけました https://dev.to/yusukeiwaki/system-testing-for-rails-application-without-capybara-using-puppeteer-5882テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol