Capybara hilft Ihnen beim Testen von Webanwendungen, indem es simuliert, wie ein echter Benutzer mit Ihrer App interagieren würde. Es ist unabhängig vom Treiber, der Ihre Tests ausführt, und verfügt über integrierte Rack::Test- und Selenium-Unterstützung. WebKit wird durch ein externes Gem unterstützt.
Wenn Sie und/oder Ihr Unternehmen Wert auf Capybara legen und einen finanziellen Beitrag zu seiner laufenden Wartung und Entwicklung leisten möchten, besuchen Sie bitte Patreon
Brauchen Sie Hilfe? Fragen Sie nach den Diskussionen (bitte kein Problem eröffnen): https://github.com/orgs/teamcapybara/discussions/categories/qa
Capybara erfordert Ruby 3.0.0 oder höher. Fügen Sie zur Installation diese Zeile zu Ihrer Gemfile
hinzu und führen Sie bundle install
aus:
gem 'capybara'
Wenn es sich bei der Anwendung, die Sie testen, um eine Rails-App handelt, fügen Sie diese Zeile zu Ihrer Testhilfsdatei hinzu:
require 'capybara/rails'
Wenn es sich bei der Anwendung, die Sie testen, um eine Rack-App, aber nicht um Rails handelt, legen Sie Capybara.app auf Ihre Rack-App fest:
Capybara . app = MyRackApp
Wenn Sie JavaScript testen müssen oder Ihre App mit einer Remote-URL interagiert (oder sich dort befindet), müssen Sie einen anderen Treiber verwenden. Wenn Sie Rails 5.0+, aber nicht die Rails-Systemtests von 5.1 verwenden, möchten Sie wahrscheinlich auch den „Server“, der zum Starten Ihrer App verwendet wird, auf Puma austauschen, um den Rails-Standardeinstellungen zu entsprechen.
Capybara . server = :puma # Until your setup is working
Capybara . server = :puma , { Silent : true } # To clean up your test output
Das cucumber-rails
Juwel verfügt über eine integrierte Capybara-Unterstützung. Wenn Sie Rails nicht verwenden, laden Sie das capybara/cucumber
-Modul manuell:
require 'capybara/cucumber'
Capybara . app = MyRackApp
Sie können Capybara DSL in Ihren Schritten verwenden, etwa so:
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
Sie können zum Capybara.javascript_driver
(standardmäßig :selenium
) wechseln, indem Sie Szenarien (oder Features) mit @javascript
markieren:
@javascript
Scenario : do something Ajaxy
When I click the Ajax link
...
Es gibt auch explizite Tags für jeden registrierten Treiber, der für Sie eingerichtet wurde ( @selenium
, @rack_test
usw.).
Laden Sie die RSpec 3.5+-Unterstützung, indem Sie die folgende Zeile hinzufügen (normalerweise zu Ihrer spec_helper.rb
Datei):
require 'capybara/rspec'
Wenn Sie Rails verwenden, geben Sie Ihre Capybara-Spezifikationen in spec/features
oder spec/system
ein (funktioniert nur, wenn Sie es in RSpec konfiguriert haben). Wenn Sie Ihre Capybara-Spezifikationen in einem anderen Verzeichnis haben, kennzeichnen Sie die Beispielgruppen mit type: :feature
oder type: :system
je nachdem, welche Art von Test Sie schreiben.
Wenn Sie Rails-Systemspezifikationen verwenden, lesen Sie bitte deren Dokumentation zur Auswahl des Treibers, den Sie verwenden möchten.
Wenn Sie Rails nicht verwenden, markieren Sie alle Beispielgruppen, in denen Sie Capybara verwenden möchten, mit type: :feature
.
Sie können Ihre Spezifikationen jetzt wie folgt schreiben:
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
Verwenden Sie js: true
, um zum Capybara.javascript_driver
(standardmäßig :selenium
) zu wechseln, oder stellen Sie eine :driver
Option bereit, um zu einem bestimmten Treiber zu wechseln. Zum Beispiel:
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 verfügt außerdem über eine integrierte DSL zum Erstellen beschreibender Abnahmetests:
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
ist in der Tat nur ein Alias für describe ..., type: :feature
, background
ist ein Alias für before
“, scenario
for it
und „ given
“ / given!
Aliase für let
/ let!
, jeweils.
Schließlich werden auch Capybara-Matcher in den Ansichtsspezifikationen unterstützt:
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
Hinweis: Wenn Sie „capybara/rspec“ benötigen, werden Proxy-Methoden installiert, um Namenskollisionen zwischen den Capybara::DSL-Methoden all
/ within
und den gleichnamigen integrierten RSpec-Matchern zu umgehen. Wenn Sie sich dafür entscheiden, „capybara/rspec“ nicht zu benötigen, können Sie die Proxy-Methoden installieren, indem Sie „capybara/rspec/matcher_proxies“ nach der Anforderung von RSpec und „capybara/dsl“ anfordern.
Wenn Sie Test::Unit
verwenden, definieren Sie eine Basisklasse für Ihre Capybara-Tests wie folgt:
require 'capybara/dsl'
class CapybaraTestCase < Test :: Unit :: TestCase
include Capybara :: DSL
def teardown
Capybara . reset_sessions!
Capybara . use_default_driver
end
end
Wenn Sie Rails-Systemtests verwenden, lesen Sie bitte deren Dokumentation für Informationen zur Auswahl des Treibers, den Sie verwenden möchten.
Wenn Sie Rails, aber keine Rails-Systemtests verwenden, fügen Sie den folgenden Code in Ihre test_helper.rb
Datei ein, um Capybara in allen von ActionDispatch::IntegrationTest
abgeleiteten Testfällen verfügbar zu machen:
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
Wenn Sie Rails nicht verwenden, definieren Sie eine Basisklasse für Ihre Capybara-Tests wie folgt:
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
Denken Sie daran, super
in allen Unterklassen aufzurufen, die teardown
überschreiben.
Um den Treiber zu wechseln, legen Sie Capybara.current_driver
fest. Zum Beispiel,
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
Befolgen Sie die obigen Anweisungen für Minitest und benötigen Sie zusätzlich capybara/minitest/spec
page . must_have_content ( 'Important!' )
Capybara verwendet dasselbe DSL, um eine Vielzahl von Browser- und Headless-Treibern zu betreiben.
Standardmäßig verwendet Capybara den :rack_test
Treiber, der schnell, aber begrenzt ist: Er unterstützt kein JavaScript und kann auch nicht auf HTTP-Ressourcen außerhalb Ihrer Rack-Anwendung zugreifen, wie z. B. Remote-APIs und OAuth-Dienste. Um diese Einschränkungen zu umgehen, können Sie einen anderen Standardtreiber für Ihre Funktionen einrichten. Wenn Sie beispielsweise lieber alles in Selenium ausführen möchten, können Sie Folgendes tun:
Capybara . default_driver = :selenium # :selenium_chrome and :selenium_chrome_headless are also registered
Wenn Sie jedoch RSpec oder Cucumber verwenden (und Ihre App ohne JS korrekt läuft), sollten Sie stattdessen den schnelleren :rack_test
als default_driver belassen und nur die Tests markieren, die einen JavaScript-fähigen Treiber mit js: true
erfordern bzw. @javascript
. Standardmäßig werden JavaScript-Tests mit dem :selenium
-Treiber ausgeführt. Sie können dies ändern, indem Sie Capybara.javascript_driver
festlegen.
Sie können den Treiber auch vorübergehend ändern (normalerweise in den Blöcken „Vor/Einrichtung“ und „Nach/Abbau“):
Capybara . current_driver = :selenium # temporarily select different driver
# tests here
Capybara . use_default_driver # switch back to default driver
Hinweis : Beim Wechseln des Treibers wird eine neue Sitzung erstellt, sodass Sie möglicherweise nicht mitten in einem Test wechseln können.
RackTest ist Capybaras Standardtreiber. Es ist in reinem Ruby geschrieben und bietet keine Unterstützung für die Ausführung von JavaScript. Da der RackTest-Treiber direkt mit Rack-Schnittstellen interagiert, ist kein Serverstart erforderlich. Dies bedeutet jedoch, dass Sie diesen Treiber nicht verwenden können, wenn Ihre Anwendung keine Rack-Anwendung ist (Rails, Sinatra und die meisten anderen Ruby-Frameworks sind Rack-Anwendungen). Darüber hinaus können Sie den RackTest-Treiber nicht zum Testen einer Remote-Anwendung oder zum Zugriff auf Remote-URLs (z. B. Weiterleitungen zu externen Sites, externen APIs oder OAuth-Diensten) verwenden, mit denen Ihre Anwendung möglicherweise interagiert.
capybara-mechanize bietet einen ähnlichen Treiber, der auf Remote-Server zugreifen kann.
RackTest kann mit einem Satz von Headern wie diesem konfiguriert werden:
Capybara . register_driver :rack_test do | app |
Capybara :: RackTest :: Driver . new ( app , headers : { 'HTTP_USER_AGENT' => 'Capybara' } )
end
Weitere Informationen finden Sie im Abschnitt zum Hinzufügen und Konfigurieren von Treibern.
Capybara unterstützt Selenium 3.5+ (Webdriver). Um Selenium verwenden zu können, müssen Sie den selenium-webdriver
Gem installieren und ihn zu Ihrer Gem-Datei hinzufügen, wenn Sie Bundler verwenden.
Capybara registriert eine Reihe benannter Treiber vor, die Selenium verwenden – das sind:
Diese sollten (mit entsprechender Softwareinstallation) in einer lokalen Desktop-Konfiguration funktionieren, Sie müssen sie jedoch möglicherweise anpassen, wenn Sie sie in einer CI-Umgebung verwenden, in der möglicherweise zusätzliche Optionen an die Browser übergeben werden müssen. Weitere Informationen finden Sie im Abschnitt zum Hinzufügen und Konfigurieren von Treibern.
Hinweis : Treiber, die den Server in einem anderen Thread ausführen, teilen möglicherweise nicht dieselbe Transaktion wie Ihre Tests, was dazu führt, dass Daten nicht zwischen Ihrem Test und dem Testserver gemeinsam genutzt werden, siehe Transaktionen und Datenbank-Setup unten.
Eine vollständige Referenz finden Sie unter rubydoc.info .
Hinweis: Standardmäßig findet Capybara nur sichtbare Elemente. Dies liegt daran, dass ein echter Benutzer nicht in der Lage wäre, mit nicht sichtbaren Elementen zu interagieren.
Hinweis : Bei allen Suchen in Capybara wird die Groß-/Kleinschreibung beachtet . Dies liegt daran, dass Capybara häufig XPath verwendet, das die Berücksichtigung der Groß- und Kleinschreibung nicht unterstützt.
Mit der Visit -Methode können Sie zu anderen Seiten navigieren:
visit ( '/projects' )
visit ( post_comments_path ( post ) )
Die Visit-Methode benötigt nur einen einzigen Parameter, die Request-Methode ist immer GET.
Sie können den aktuellen Pfad der Browsersitzung abrufen und ihn mit dem have_current_path
-Matcher testen:
expect ( page ) . to have_current_path ( post_comments_path ( post ) )
Hinweis : Sie können den aktuellen Pfad auch bestätigen, indem Sie den Wert von current_path
direkt testen. Die Verwendung des have_current_path
-Matchers ist jedoch sicherer, da er das Warteverhalten von Capybara nutzt, um sicherzustellen, dass vorhergehende Aktionen (z. B. click_link
) abgeschlossen wurden.
Vollständige Referenz: Capybara::Node::Actions
Sie können mit der Webanwendung interagieren, indem Sie Links und Schaltflächen folgen. Capybara folgt automatisch allen Weiterleitungen und sendet mit Schaltflächen verknüpfte Formulare.
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' )
Vollständige Referenz: Capybara::Node::Actions
Es gibt eine Reihe von Tools für die Interaktion mit Formularelementen:
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' )
Vollständige Referenz: Capybara::Node::Matchers
Capybara verfügt über zahlreiche Optionen zum Abfragen der Seite auf das Vorhandensein bestimmter Elemente sowie zum Arbeiten mit und Bearbeiten dieser Elemente.
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' )
Hinweis: Die Negativformen wie has_no_selector?
unterscheiden sich von not has_selector?
. Eine Erklärung finden Sie im Abschnitt über asynchrones JavaScript.
Sie können diese mit den Magic Matchern von RSpec verwenden:
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' )
Vollständige Referenz: Capybara::Node::Finders
Sie können auch bestimmte Elemente finden, um sie zu manipulieren:
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 ] }
Wenn Sie Elemente anhand zusätzlicher Attribute/Eigenschaften suchen müssen, können Sie auch einen Filterblock übergeben, der im normalen Warteverhalten überprüft wird. Wenn Sie dies häufig verwenden müssen, ist es möglicherweise besser, einen benutzerdefinierten Selektor oder einen Filter zu einem vorhandenen Selektor hinzuzufügen.
find_field ( 'First Name' ) { | el | el [ 'data-xyz' ] == '123' }
find ( "#img_loading" ) { | img | img [ 'complete' ] == true }
Hinweis : find
wartet darauf, dass ein Element auf der Seite erscheint, wie im Abschnitt Ajax erläutert. Wenn das Element nicht angezeigt wird, wird ein Fehler ausgegeben.
Für diese Elemente stehen alle Capybara-DSL-Methoden zur Verfügung, sodass Sie sie auf bestimmte Teile der Seite beschränken können:
find ( '#navigation' ) . click_link ( 'Home' )
expect ( find ( '#navigation' ) ) . to have_button ( 'Sign out' )
Capybara ermöglicht es, bestimmte Aktionen, wie z. B. die Interaktion mit Formularen oder das Klicken auf Links und Schaltflächen, auf einen bestimmten Bereich der Seite zu beschränken. Zu diesem Zweck können Sie die generische Within -Methode verwenden. Optional können Sie angeben, welche Art von Selektor verwendet werden soll.
within ( "li#employee" ) do
fill_in 'Name' , with : 'Jimmy'
end
within ( :xpath , ".//li[@id='employee']" ) do
fill_in 'Name' , with : 'Jimmy'
end
Es gibt spezielle Methoden, um den Bereich auf ein bestimmtes Feldset zu beschränken, das entweder durch eine ID oder den Text des Legenden-Tags des Feldsets identifiziert wird, und auf eine bestimmte Tabelle, die entweder durch die ID oder den Text des Beschriftungs-Tags der Tabelle identifiziert wird.
within_fieldset ( 'Employee' ) do
fill_in 'Name' , with : 'Jimmy'
end
within_table ( 'Employee' ) do
fill_in 'Name' , with : 'Jimmy'
end
Capybara bietet einige Methoden, um das Suchen und Wechseln von Fenstern zu erleichtern:
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
In Treibern, die es unterstützen, können Sie JavaScript problemlos ausführen:
page . execute_script ( "$('body').empty()" )
Bei einfachen Ausdrücken können Sie das Ergebnis des Skripts zurückgeben.
result = page . evaluate_script ( '4 + 4' ) ;
Kompliziertere Skripte müssen Sie als einen Ausdruck schreiben.
result = page . evaluate_script ( <<~JS , 3 , element )
(function(n, el){
var val = parseInt(el.value, 10);
return n+val;
})(arguments[0], arguments[1])
JS
In Treibern, die dies unterstützen, können Sie Warnungen, Bestätigungen und Eingabeaufforderungen annehmen, ablehnen und darauf reagieren.
Sie können Warnmeldungen akzeptieren, indem Sie den Code, der eine Warnung erzeugt, in einen Block einschließen:
accept_alert 'optional text or regex' do
click_link ( 'Show Alert' )
end
Sie können eine Bestätigung auch akzeptieren oder verwerfen, indem Sie sie in einen Block einschließen:
accept_confirm 'optional text' do
click_link ( 'Show Confirm' )
end
dismiss_confirm 'optional text' do
click_link ( 'Show Confirm' )
end
Sie können Eingabeaufforderungen auch annehmen oder ablehnen und außerdem Text zum Ausfüllen der Antwort angeben:
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
Alle modalen Methoden geben die angezeigte Nachricht zurück. Sie können also auf die Eingabeaufforderungsnachricht zugreifen, indem Sie die Rückgabe einer Variablen zuweisen:
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?' )
Es kann hilfreich sein, einen Schnappschuss der Seite in ihrem aktuellen Zustand zu machen und sie sich anzusehen:
save_and_open_page
Sie können den aktuellen Status des DOM auch als String mithilfe von page.html abrufen.
print page . html
Dies ist vor allem zum Debuggen nützlich. Sie sollten das Testen anhand des Inhalts von page.html
vermeiden und stattdessen die aussagekräftigeren Finder-Methoden verwenden.
Schließlich können Sie in Treibern, die dies unterstützen, einen Screenshot speichern:
page . save_screenshot ( 'screenshot.png' )
Oder lassen Sie es speichern und automatisch öffnen:
save_and_open_screenshot
Screenshots werden in Capybara.save_path
relativ zum App-Verzeichnis gespeichert. Wenn Sie capybara/rails
benötigt haben, wird Capybara.save_path
standardmäßig auf tmp/capybara
gesetzt.
Helfer und Matcher, die Selektoren akzeptieren, haben eine gemeinsame Methodensignatur, die Folgendes umfasst:
Diese Argumente sind normalerweise auf die eine oder andere Weise optional.
Das Namensargument bestimmt den zu verwendenden Selektor. Das Argument ist optional, wenn ein Helfer den Selektornamen explizit übergibt (zum Beispiel verwendet find_field
:field
, find_link
verwendet :link
usw.):
page . html # => '<a href="/">Home</a>'
page . find ( :link ) == page . find_link
page . html # => '<input>'
page . find ( :field ) == page . find_field
Das Locator-Argument stellt normalerweise Informationen dar, die ein Element, das mit dem Selektor übereinstimmt, am aussagekräftigsten von einem Element unterscheiden können, das dies nicht tut:
page . html # => '<div id="greeting">Hello world</div>'
page . find ( :css , 'div' ) . text # => 'Hello world'
page . find ( :xpath , './/div' ) . text # => 'Hello world'
Allzweck-Findermethoden wie find
und all
können den Locator als erstes Positionsargument akzeptieren, wenn die Methode den Standardwert aus der Capybara.default_selector
-Konfiguration ableiten kann: