Capybara は、実際のユーザーがアプリをどのように操作するかをシミュレートすることで、Web アプリケーションをテストするのに役立ちます。テストを実行するドライバーに依存せず、Rack::Test および Selenium サポートが組み込まれています。WebKit は外部 gem を通じてサポートされます。
あなたやあなたの会社が Capybara に価値を見出しており、その継続的なメンテナンスと開発に財政的に貢献したい場合は、Patreon にアクセスしてください。
助けが必要ですか?ディスカッションについて質問します (問題を開かないでください): https://github.com/orgs/teamcapybara/Discussions/categories/qa
Capybara には Ruby 3.0.0 以降が必要です。インストールするには、次の行をGemfile
に追加し、 bundle install
実行します。
gem 'capybara'
テストしているアプリケーションが Rails アプリの場合は、次の行をテスト ヘルパー ファイルに追加します。
require 'capybara/rails'
テストしているアプリケーションが Rails ではなく Rack アプリである場合は、Capybara.app を Rack アプリに設定します。
Capybara . app = MyRackApp
JavaScript をテストする必要がある場合、またはアプリがリモート URL と対話する (またはリモート URL にある) 場合は、別のドライバーを使用する必要があります。 Rails 5.0 以降を使用しているが、5.1 の Rails システム テストを使用していない場合は、Rails のデフォルトと一致させるために、アプリの起動に使用される「サーバー」を Puma に交換することも必要になるでしょう。
Capybara . server = :puma # Until your setup is working
Capybara . server = :puma , { Silent : true } # To clean up your test output
cucumber-rails
gem には Capybara サポートが組み込まれています。 Rails を使用していない場合は、 capybara/cucumber
モジュールを手動でロードします。
require 'capybara/cucumber'
Capybara . app = MyRackApp
次のように、ステップで Capybara DSL を使用できます。
When /I sign in/ do
within ( "#session" ) do
fill_in 'Email' , with : '[email protected]'
fill_in 'Password' , with : 'password'
end
click_button 'Sign in'
end
@javascript
でシナリオ (または機能) をタグ付けすることで、 Capybara.javascript_driver
(デフォルトでは:selenium
) に切り替えることができます。
@javascript
Scenario : do something Ajaxy
When I click the Ajax link
...
登録済みドライバーごとに設定された明示的なタグもあります ( @selenium
、 @rack_test
など)。
次の行を (通常はspec_helper.rb
ファイルに) 追加して、RSpec 3.5+ サポートをロードします。
require 'capybara/rspec'
Rails を使用している場合は、Capybara 仕様をspec/features
またはspec/system
(RSpec で構成されている場合にのみ機能します) に置き、Capybara 仕様が別のディレクトリにある場合は、サンプル グループにtype: :feature
作成しているテストのタイプに応じて、 type: :feature
またはtype: :system
。
Rails システム仕様を使用している場合は、使用するドライバーを選択するためのドキュメントを参照してください。
Rails を使用していない場合は、Capybara を使用するすべてのサンプル グループにtype: :feature
のタグを付けます。
次のように仕様を記述できるようになりました。
describe "the signin process" , type : :feature do
before :each do
User . create ( email : '[email protected]' , password : 'password' )
end
it "signs me in" do
visit '/sessions/new'
within ( "#session" ) do
fill_in 'Email' , with : '[email protected]'
fill_in 'Password' , with : 'password'
end
click_button 'Sign in'
expect ( page ) . to have_content 'Success'
end
end
js: true
を使用してCapybara.javascript_driver
(デフォルトでは:selenium
) に切り替えるか、 :driver
オプションを指定して 1 つの特定のドライバーに切り替えます。例えば:
describe 'some stuff which requires js' , js : true do
it 'will use the default js driver'
it 'will switch to one specific driver' , driver : :selenium
end
Capybara には、記述的な受け入れテストを作成するための DSL も組み込まれています。
feature "Signing in" do
background do
User . create ( email : '[email protected]' , password : 'caplin' )
end
scenario "Signing in with correct credentials" do
visit '/sessions/new'
within ( "#session" ) do
fill_in 'Email' , with : '[email protected]'
fill_in 'Password' , with : 'caplin'
end
click_button 'Sign in'
expect ( page ) . to have_content 'Success'
end
given ( :other_user ) { User . create ( email : '[email protected]' , password : 'rous' ) }
scenario "Signing in as another user" do
visit '/sessions/new'
within ( "#session" ) do
fill_in 'Email' , with : other_user . email
fill_in 'Password' , with : other_user . password
end
click_button 'Sign in'
expect ( page ) . to have_content 'Invalid email or password'
end
end
feature
は実際には、 describe ..., type: :feature
エイリアスであり、 background
before
、 scenario
for it
、およびgiven
/ given!
のエイリアスです。 let
/ let!
の別名、 それぞれ。
最後に、Capybara マッチャーもビュー仕様でサポートされています。
RSpec . describe "todos/show.html.erb" , type : :view do
it "displays the todo title" do
assign :todo , Todo . new ( title : "Buy milk" )
render
expect ( rendered ) . to have_css ( "header h1" , text : "Buy milk" )
end
end
注: 「capybara/rspec」が必要な場合、Capybara::DSL メソッドall
/ within
と同じ名前の組み込み RSpec マッチャー間の名前の衝突を回避するために、プロキシ メソッドがインストールされます。 「capybara/rspec」を要求しないことを選択した場合は、RSpec と 'capybara/dsl' を要求した後で 'capybara/rspec/matcher_proxies' を要求することでプロキシ メソッドをインストールできます。
Test::Unit
使用している場合は、次のように Capybara テストの基本クラスを定義します。
require 'capybara/dsl'
class CapybaraTestCase < Test :: Unit :: TestCase
include Capybara :: DSL
def teardown
Capybara . reset_sessions!
Capybara . use_default_driver
end
end
Rails システム テストを使用している場合は、使用するドライバーの選択についてそのドキュメントを参照してください。
Rails を使用しているが、Rails システム テストは使用していない場合は、 test_helper.rb
ファイルに次のコードを追加して、 ActionDispatch::IntegrationTest
から派生するすべてのテスト ケースで Capybara を使用できるようにします。
require 'capybara/rails'
require 'capybara/minitest'
class ActionDispatch :: IntegrationTest
# Make the Capybara DSL available in all integration tests
include Capybara :: DSL
# Make `assert_*` methods behave like Minitest assertions
include Capybara :: Minitest :: Assertions
# Reset sessions and driver between tests
teardown do
Capybara . reset_sessions!
Capybara . use_default_driver
end
end
Rails を使用していない場合は、次のように Capybara テストの基本クラスを定義します。
require 'capybara/minitest'
class CapybaraTestCase < Minitest :: Test
include Capybara :: DSL
include Capybara :: Minitest :: Assertions
def teardown
Capybara . reset_sessions!
Capybara . use_default_driver
end
end
teardown
をオーバーライドするサブクラスでは必ずsuper
呼び出してください。
ドライバーを切り替えるには、 Capybara.current_driver
を設定します。例えば、
class BlogTest < ActionDispatch :: IntegrationTest
setup do
Capybara . current_driver = Capybara . javascript_driver # :selenium by default
end
test 'shows blog posts' do
# ... this test is run with Selenium ...
end
end
Minitest については上記の手順に従い、さらに capybara/minitest/spec が必要です
page . must_have_content ( 'Important!' )
Capybara は同じ DSL を使用して、さまざまなブラウザおよびヘッドレス ドライバーを駆動します。
デフォルトでは、Capybara は:rack_test
ドライバーを使用します。これは高速ですが制限があります。JavaScript はサポートされておらず、リモート API や OAuth サービスなど、Rack アプリケーションの外部の HTTP リソースにもアクセスできません。これらの制限を回避するには、機能に別のデフォルト ドライバーを設定します。たとえば、すべてを Selenium で実行したい場合は、次のようにすることができます。
Capybara . default_driver = :selenium # :selenium_chrome and :selenium_chrome_headless are also registered
ただし、RSpec または Cucumber を使用している場合 (およびアプリが JS なしで正しく実行される場合)、より高速な:rack_test
default_driverとして残し、 js: true
使用して JavaScript 対応ドライバーを必要とするテストのみをマークすることを検討することをお勧めします。または@javascript
、それぞれ。デフォルトでは、JavaScript テストは:selenium
ドライバーを使用して実行されます。これはCapybara.javascript_driver
設定することで変更できます。
ドライバーを一時的に変更することもできます (通常は、Before/setup ブロックと After/teardown ブロックで)。
Capybara . current_driver = :selenium # temporarily select different driver
# tests here
Capybara . use_default_driver # switch back to default driver
注: ドライバーを切り替えると新しいセッションが作成されるため、テストの途中では切り替えることができない場合があります。
RackTest は Capybara のデフォルトのドライバーです。これは純粋な Ruby で書かれており、JavaScript の実行はサポートされていません。 RackTest ドライバーは Rack インターフェイスと直接対話するため、サーバーを起動する必要はありません。ただし、これは、アプリケーションが Rack アプリケーションでない場合 (Rails、Sinatra、およびその他のほとんどの Ruby フレームワークは Rack アプリケーションです)、このドライバーは使用できないことを意味します。さらに、RackTest ドライバーを使用してリモート アプリケーションをテストしたり、アプリケーションが対話する可能性のあるリモート URL (外部サイト、外部 API、OAuth サービスなど) にアクセスしたりすることはできません。
capybara-mechanize は、リモート サーバーにアクセスできる同様のドライバーを提供します。
RackTest は、次のような一連のヘッダーを使用して構成できます。
Capybara . register_driver :rack_test do | app |
Capybara :: RackTest :: Driver . new ( app , headers : { 'HTTP_USER_AGENT' => 'Capybara' } )
end
ドライバーの追加と構成に関するセクションを参照してください。
Capybara は Selenium 3.5+ (Webdriver) をサポートしています。 Selenium を使用するには、 selenium-webdriver
gem をインストールし、バンドラーを使用している場合は Gemfile に追加する必要があります。
Capybara は、Selenium を使用する多数の名前付きドライバーを事前登録しています。それらは次のとおりです。
これらは、ローカル デスクトップ構成では (関連するソフトウェアをインストールすると) 機能するはずですが、追加のオプションをブラウザに渡す必要がある CI 環境で使用する場合は、カスタマイズが必要になる場合があります。ドライバーの追加と構成に関するセクションを参照してください。
注: 別のスレッドでサーバーを実行するドライバーは、テストと同じトランザクションを共有しない可能性があり、その結果、テストとテスト サーバーの間でデータが共有されなくなります。以下のトランザクションとデータベースのセットアップを参照してください。
完全なリファレンスは、rubydoc.info で入手できます。
注: デフォルトでは、Capybara は表示されている要素のみを検索します。これは、実際のユーザーは目に見えない要素を操作できないためです。
注: Capybara でのすべての検索では大文字と小文字が区別されます。これは、Capybara が大文字と小文字の区別をサポートしていない XPath を頻繁に使用するためです。
visitメソッドを使用して他のページに移動できます。
visit ( '/projects' )
visit ( post_comments_path ( post ) )
visit メソッドは 1 つのパラメータのみを受け取り、リクエスト メソッドは常にGET です。
ブラウジング セッションの現在のパスを取得し、 have_current_path
マッチャーを使用してテストできます。
expect ( page ) . to have_current_path ( post_comments_path ( post ) )
注: current_path
の値を直接テストして、現在のパスをアサートすることもできます。ただし、 have_current_path
マッチャーを使用する方が安全です。これは、Capybara の待機動作を使用して、先行するアクション ( click_link
など) が完了していることを確認するためです。
完全なリファレンス: Capybara::Node::Actions
リンクやボタンに従って Web アプリを操作できます。 Capybara はリダイレクトを自動的に追跡し、ボタンに関連付けられたフォームを送信します。
click_link ( 'id-of-link' )
click_link ( 'Link Text' )
click_button ( 'Save' )
click_on ( 'Link Text' ) # clicks on either links or buttons
click_on ( 'Button Value' )
完全なリファレンス: Capybara::Node::Actions
フォーム要素を操作するためのツールが多数あります。
fill_in ( 'First Name' , with : 'John' )
fill_in ( 'Password' , with : 'Seekrit' )
fill_in ( 'Description' , with : 'Really Long Text...' )
choose ( 'A Radio Button' )
check ( 'A Checkbox' )
uncheck ( 'A Checkbox' )
attach_file ( 'Image' , '/path/to/image.jpg' )
select ( 'Option' , from : 'Select Box' )
完全なリファレンス: Capybara::Node::Matchers
Capybara には、ページに特定の要素の存在を問い合わせたり、それらの要素を操作したりするための豊富なオプション セットがあります。
page . has_selector? ( 'table tr' )
page . has_selector? ( :xpath , './/table/tr' )
page . has_xpath? ( './/table/tr' )
page . has_css? ( 'table tr.foo' )
page . has_content? ( 'foo' )
注: has_no_selector?
のような否定形not has_selector?
。説明については、非同期 JavaScript に関するセクションを参照してください。
これらは RSpec のマジック マッチャーで使用できます。
expect ( page ) . to have_selector ( 'table tr' )
expect ( page ) . to have_selector ( :xpath , './/table/tr' )
expect ( page ) . to have_xpath ( './/table/tr' )
expect ( page ) . to have_css ( 'table tr.foo' )
expect ( page ) . to have_content ( 'foo' )
完全なリファレンス: Capybara::Node::Finders
特定の要素を検索して操作することもできます。
find_field ( 'First Name' ) . value
find_field ( id : 'my_field' ) . value
find_link ( 'Hello' , :visible => :all ) . visible?
find_link ( class : [ 'some_class' , 'some_other_class' ] , :visible => :all ) . visible?
find_button ( 'Send' ) . click
find_button ( value : '1234' ) . click
find ( :xpath , ".//table/tr" ) . click
find ( "#overlay" ) . find ( "h1" ) . click
all ( 'a' ) . each { | a | a [ :href ] }
追加の属性/プロパティによって要素を検索する必要がある場合は、通常の待機動作内でチェックされるフィルター ブロックを渡すこともできます。これを頻繁に使用する必要がある場合は、カスタム セレクターを追加するか、既存のセレクターにフィルターを追加することをお勧めします。
find_field ( 'First Name' ) { | el | el [ 'data-xyz' ] == '123' }
find ( "#img_loading" ) { | img | img [ 'complete' ] == true }
注: Ajax セクションで説明したように、 find
要素がページに表示されるまで待機します。要素が表示されない場合は、エラーが発生します。
これらの要素にはすべて、利用可能な Capybara DSL メソッドがすべて含まれているため、ページの特定の部分に制限できます。
find ( '#navigation' ) . click_link ( 'Home' )
expect ( find ( '#navigation' ) ) . to have_button ( 'Sign out' )
Capybara を使用すると、フォームの操作やリンクやボタンのクリックなど、特定のアクションをページの特定の領域内に制限できます。この目的のために、ジェネリックのinsideメソッドを使用できます。必要に応じて、使用するセレクターの種類を指定できます。
within ( "li#employee" ) do
fill_in 'Name' , with : 'Jimmy'
end
within ( :xpath , ".//li[@id='employee']" ) do
fill_in 'Name' , with : 'Jimmy'
end
フィールドセットの凡例タグの ID またはテキストで識別される特定のフィールドセットと、テーブルのキャプション タグの ID またはテキストで識別される特定のテーブルにスコープを制限するための特別なメソッドがあります。
within_fieldset ( 'Employee' ) do
fill_in 'Name' , with : 'Jimmy'
end
within_table ( 'Employee' ) do
fill_in 'Name' , with : 'Jimmy'
end
Capybara は、ウィンドウの検索と切り替えを容易にするいくつかの方法を提供します。
facebook_window = window_opened_by do
click_button 'Like'
end
within_window facebook_window do
find ( '#login_email' ) . set ( '[email protected]' )
find ( '#login_password' ) . set ( 'qwerty' )
click_button 'Submit'
end
これをサポートするドライバーでは、JavaScript を簡単に実行できます。
page . execute_script ( "$('body').empty()" )
単純な式の場合は、スクリプトの結果を返すことができます。
result = page . evaluate_script ( '4 + 4' ) ;
より複雑なスクリプトの場合は、それらを 1 つの式として記述する必要があります。
result = page . evaluate_script ( <<~JS , 3 , element )
(function(n, el){
var val = parseInt(el.value, 10);
return n+val;
})(arguments[0], arguments[1])
JS
これをサポートするドライバーでは、アラート、確認、およびプロンプトを受け入れ、無視し、応答することができます。
アラートを生成するコードをブロックでラップすることで、アラート メッセージを受け入れることができます。
accept_alert 'optional text or regex' do
click_link ( 'Show Alert' )
end
確認をブロックで囲むことによって、承認または拒否することもできます。
accept_confirm 'optional text' do
click_link ( 'Show Confirm' )
end
dismiss_confirm 'optional text' do
click_link ( 'Show Confirm' )
end
プロンプトを受け入れるか拒否することもでき、応答として入力するテキストを指定することもできます。
accept_prompt ( 'optional text' , with : 'Linus Torvalds' ) do
click_link ( 'Show Prompt About Linux' )
end
dismiss_prompt ( 'optional text' ) do
click_link ( 'Show Prompt About Linux' )
end
すべてのモーダル メソッドは、表示されたメッセージを返します。したがって、return を変数に代入することで、プロンプト メッセージにアクセスできます。
message = accept_prompt ( with : 'Linus Torvalds' ) do
click_link ( 'Show Prompt About Linux' )
end
expect ( message ) . to eq ( 'Who is the chief architect of Linux?' )
現在のページのスナップショットを取得して確認すると便利です。
save_and_open_page
page.htmlを使用して、DOM の現在の状態を文字列として取得することもできます。
print page . html
これは主にデバッグに役立ちます。 page.html
のコンテンツに対するテストは避け、代わりにより表現力豊かなファインダー メソッドを使用する必要があります。
最後に、これをサポートするドライバーでは、スクリーンショットを保存できます。
page . save_screenshot ( 'screenshot.png' )
または、保存して自動的に開くようにします。
save_and_open_screenshot
スクリーンショットは、アプリ ディレクトリを基準としたCapybara.save_path
に保存されます。 capybara/rails
が必要な場合、 Capybara.save_path
デフォルトでtmp/capybara
になります。
セレクターを受け入れるヘルパーとマッチャーは、次のような共通のメソッド シグネチャを共有します。
これらの引数は通常、何らかの形でオプションです。
name 引数によって、使用するセレクターが決まります。ヘルパーがセレクター名を明示的に伝える場合、引数はオプションです (たとえば、 find_field
:field
使用し、 find_link
:link
使用します)。
page . html # => '<a href="/">Home</a>'
page . find ( :link ) == page . find_link
page . html # => '<input>'
page . find ( :field ) == page . find_field
ロケーター引数は通常、セレクターに一致する要素とそうでない要素を最も有意義に区別できる情報を表します。
page . html # => '<div id="greeting">Hello world</div>'
page . find ( :css , 'div' ) . text # => 'Hello world'
page . find ( :xpath , './/div' ) . text # => 'Hello world'
find
やall
などの汎用ファインダー メソッドは、メソッドがCapybara.default_selector
設定からデフォルト値を推測できる場合、最初の位置引数としてロケーターを受け入れることができます。