Capybara te ayuda a probar aplicaciones web simulando cómo interactuaría un usuario real con tu aplicación. Es independiente del controlador que ejecuta las pruebas y viene con soporte para Rack::Test y Selenium integrado. WebKit es compatible a través de una gema externa.
Si usted y/o su empresa encuentran valor en Capybara y desean contribuir financieramente a su mantenimiento y desarrollo continuo, visite Patreon.
¿Necesitar ayuda? Pregunte en las discusiones (no abra un problema): https://github.com/orgs/teamcapybara/discussions/categories/qa
Capybara requiere Ruby 3.0.0 o posterior. Para instalar, agregue esta línea a su Gemfile
y ejecute bundle install
:
gem 'capybara'
Si la aplicación que está probando es una aplicación Rails, agregue esta línea a su archivo auxiliar de prueba:
require 'capybara/rails'
Si la aplicación que está probando es una aplicación Rack, pero no Rails, configure Capybara.app en su aplicación Rack:
Capybara . app = MyRackApp
Si necesita probar JavaScript, o si su aplicación interactúa con (o está ubicada en) una URL remota, deberá usar un controlador diferente. Si usa Rails 5.0+, pero no usa las pruebas del sistema Rails de 5.1, probablemente también querrá cambiar el "servidor" usado para iniciar su aplicación a Puma para que coincida con los valores predeterminados de Rails.
Capybara . server = :puma # Until your setup is working
Capybara . server = :puma , { Silent : true } # To clean up your test output
La joya cucumber-rails
viene con soporte de Carpincho incorporado. Si no está utilizando Rails, cargue manualmente el módulo capybara/cucumber
:
require 'capybara/cucumber'
Capybara . app = MyRackApp
Puedes usar Capybara DSL en tus pasos, así:
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
Puede cambiar a Capybara.javascript_driver
( :selenium
de forma predeterminada) etiquetando escenarios (o características) con @javascript
:
@javascript
Scenario : do something Ajaxy
When I click the Ajax link
...
También hay etiquetas explícitas para cada controlador registrado configurado para usted ( @selenium
, @rack_test
, etc.).
Cargue la compatibilidad con RSpec 3.5+ agregando la siguiente línea (normalmente a su archivo spec_helper.rb
):
require 'capybara/rspec'
Si está utilizando Rails, coloque sus especificaciones de Capybara en spec/features
o spec/system
(solo funciona si lo tiene configurado en RSpec) y si tiene sus especificaciones de Capybara en un directorio diferente, etiquete los grupos de ejemplo con type: :feature
o type: :system
dependiendo del tipo de prueba que esté escribiendo.
Si está utilizando las especificaciones del sistema Rails, consulte su documentación para seleccionar el controlador que desea utilizar.
Si no está utilizando Rails, etiquete todos los grupos de ejemplo en los que desea utilizar Capybara con type: :feature
.
Ahora puedes escribir tus especificaciones así:
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
Utilice js: true
para cambiar a Capybara.javascript_driver
( :selenium
de forma predeterminada) o proporcione una opción :driver
para cambiar a un controlador específico. Por ejemplo:
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 también viene con un DSL integrado para crear pruebas de aceptación descriptivas:
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
De hecho, feature
es solo un alias para describe ..., type: :feature
, background
es un alias para before
, scenario
para it
y given
/ given!
alias para let
/ let!
, respectivamente.
Finalmente, los emparejadores de Carpincho también son compatibles con las especificaciones de visualización:
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
Nota: Cuando es necesario, se instalan métodos proxy 'capybara/rspec' para evitar colisiones de nombres entre los métodos Capybara::DSL all
/ within
y los comparadores RSpec integrados con nombres idénticos. Si opta por no requerir 'capybara/rspec', puede instalar los métodos proxy solicitando 'capybara/rspec/matcher_proxies' después de requerir RSpec y 'capybara/dsl'.
Si está utilizando Test::Unit
, defina una clase base para sus pruebas de Capybara de esta manera:
require 'capybara/dsl'
class CapybaraTestCase < Test :: Unit :: TestCase
include Capybara :: DSL
def teardown
Capybara . reset_sessions!
Capybara . use_default_driver
end
end
Si está utilizando pruebas del sistema Rails, consulte su documentación para obtener información sobre cómo seleccionar el controlador que desea utilizar.
Si está utilizando Rails, pero no utiliza pruebas del sistema Rails, agregue el siguiente código en su archivo test_helper.rb
para que Capybara esté disponible en todos los casos de prueba derivados de ActionDispatch::IntegrationTest
:
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
Si no estás usando Rails, define una clase base para tus pruebas de Capybara así:
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
Recuerde llamar super
en cualquier subclase que anule teardown
.
Para cambiar el controlador, configure Capybara.current_driver
. Por ejemplo,
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
Siga las instrucciones anteriores para Minitest y, además, solicite capibara/minitest/spec
page . must_have_content ( 'Important!' )
Capybara utiliza el mismo DSL para controlar una variedad de navegadores y controladores sin cabeza.
De forma predeterminada, Capybara utiliza el controlador :rack_test
, que es rápido pero limitado: no admite JavaScript ni puede acceder a recursos HTTP fuera de su aplicación Rack, como API remotas y servicios OAuth. Para sortear estas limitaciones, puede configurar un controlador predeterminado diferente para sus funciones. Por ejemplo, si prefieres ejecutar todo en Selenium, puedes hacer:
Capybara . default_driver = :selenium # :selenium_chrome and :selenium_chrome_headless are also registered
Sin embargo, si está utilizando RSpec o Cucumber (y su aplicación se ejecuta correctamente sin JS), es posible que desee considerar dejar el :rack_test
más rápido como default_driver y marcar solo aquellas pruebas que requieren un controlador compatible con JavaScript usando js: true
o @javascript
, respectivamente. De forma predeterminada, las pruebas de JavaScript se ejecutan utilizando el controlador :selenium
. Puedes cambiar esto configurando Capybara.javascript_driver
.
También puede cambiar el controlador temporalmente (normalmente en los bloques Antes/configuración y Después/desmontaje):
Capybara . current_driver = :selenium # temporarily select different driver
# tests here
Capybara . use_default_driver # switch back to default driver
Nota : cambiar el controlador crea una nueva sesión, por lo que es posible que no pueda cambiar en medio de una prueba.
RackTest es el controlador predeterminado de Capybara. Está escrito en Ruby puro y no tiene soporte para ejecutar JavaScript. Dado que el controlador RackTest interactúa directamente con las interfaces de Rack, no requiere que se inicie un servidor. Sin embargo, esto significa que si su aplicación no es una aplicación Rack (Rails, Sinatra y la mayoría de los otros frameworks Ruby son aplicaciones Rack), entonces no podrá usar este controlador. Además, no puede utilizar el controlador RackTest para probar una aplicación remota ni para acceder a URL remotas (por ejemplo, redirecciones a sitios externos, API externas o servicios OAuth) con las que su aplicación podría interactuar.
capybara-mechanize proporciona un controlador similar que puede acceder a servidores remotos.
RackTest se puede configurar con un conjunto de encabezados como este:
Capybara . register_driver :rack_test do | app |
Capybara :: RackTest :: Driver . new ( app , headers : { 'HTTP_USER_AGENT' => 'Capybara' } )
end
Consulte la sección sobre cómo agregar y configurar controladores.
Capybara es compatible con Selenium 3.5+ (Webdriver). Para usar Selenium, necesitarás instalar la gema selenium-webdriver
y agregarla a tu Gemfile si estás usando el paquete.
Capybara registra previamente una serie de controladores nombrados que usan Selenium; son:
Estos deberían funcionar (con la instalación de software relevante) en una configuración de escritorio local, pero es posible que deba personalizarlos si los usa en un entorno de CI donde es posible que sea necesario pasar opciones adicionales a los navegadores. Consulte la sección sobre cómo agregar y configurar controladores.
Nota : los controladores que ejecutan el servidor en un subproceso diferente pueden no compartir la misma transacción que sus pruebas, lo que provoca que los datos no se compartan entre su prueba y el servidor de prueba; consulte Transacciones y configuración de la base de datos a continuación.
Una referencia completa está disponible en rubydoc.info .
Nota: Por defecto, Carpincho sólo localizará elementos visibles. Esto se debe a que un usuario real no podría interactuar con elementos no visibles.
Nota : Todas las búsquedas en Carpincho distinguen entre mayúsculas y minúsculas . Esto se debe a que Capybara utiliza mucho XPath, que no admite la distinción entre mayúsculas y minúsculas.
Puede utilizar el método de visita para navegar a otras páginas:
visit ( '/projects' )
visit ( post_comments_path ( post ) )
El método de visita solo toma un único parámetro, el método de solicitud siempre es GET.
Puede obtener la ruta actual de la sesión de navegación y probarla usando el comparador have_current_path
:
expect ( page ) . to have_current_path ( post_comments_path ( post ) )
Nota : También puede afirmar la ruta actual probando el valor de current_path
directamente. Sin embargo, usar el comparador have_current_path
es más seguro ya que utiliza el comportamiento de espera de Capybara para garantizar que las acciones anteriores (como click_link
) se hayan completado.
Referencia completa: Carpincho::Nodo::Acciones
Puede interactuar con la aplicación web siguiendo enlaces y botones. Capybara sigue automáticamente cualquier redireccionamiento y envía formularios asociados con botones.
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' )
Referencia completa: Carpincho::Nodo::Acciones
Existen varias herramientas para interactuar con los elementos del formulario:
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' )
Referencia completa: Carpincho::Nodo::Matchers
Capybara tiene un amplio conjunto de opciones para consultar la página sobre la existencia de ciertos elementos y trabajar con esos elementos y manipularlos.
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' )
Nota: ¿Las formas negativas como has_no_selector?
son diferentes de not has_selector?
. Lea la sección sobre JavaScript asincrónico para obtener una explicación.
Puedes usarlos con los emparejadores mágicos de 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' )
Referencia completa: Carpincho::Nodo::Buscadores
También puedes encontrar elementos específicos, para poder manipularlos:
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 ] }
Si necesita encontrar elementos por atributos/propiedades adicionales, también puede pasar un bloque de filtro, que se verificará dentro del comportamiento de espera normal. Si necesita usar esto con frecuencia, es mejor que agregue un selector personalizado o agregue un filtro a un selector existente.
find_field ( 'First Name' ) { | el | el [ 'data-xyz' ] == '123' }
find ( "#img_loading" ) { | img | img [ 'complete' ] == true }
Nota : find
esperará a que aparezca un elemento en la página, como se explica en la sección Ajax. Si el elemento no aparece generará un error.
Todos estos elementos tienen todos los métodos DSL de Capybara disponibles, por lo que puedes restringirlos a partes específicas de la página:
find ( '#navigation' ) . click_link ( 'Home' )
expect ( find ( '#navigation' ) ) . to have_button ( 'Sign out' )
Capybara permite restringir ciertas acciones, como interactuar con formularios o hacer clic en enlaces y botones, dentro de un área específica de la página. Para ello, puede utilizar el método genérico inside . Opcionalmente, puede especificar qué tipo de selector utilizar.
within ( "li#employee" ) do
fill_in 'Name' , with : 'Jimmy'
end
within ( :xpath , ".//li[@id='employee']" ) do
fill_in 'Name' , with : 'Jimmy'
end
Existen métodos especiales para restringir el alcance a un conjunto de campos específico, identificado por una identificación o el texto de la etiqueta de leyenda del conjunto de campos, y a una tabla específica, identificada por una identificación o el texto de la etiqueta de título de la tabla.
within_fieldset ( 'Employee' ) do
fill_in 'Name' , with : 'Jimmy'
end
within_table ( 'Employee' ) do
fill_in 'Name' , with : 'Jimmy'
end
Carpincho proporciona algunos métodos para facilitar la búsqueda y el cambio de ventanas:
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
En los controladores que lo admiten, puede ejecutar JavaScript fácilmente:
page . execute_script ( "$('body').empty()" )
Para expresiones simples, puede devolver el resultado del script.
result = page . evaluate_script ( '4 + 4' ) ;
Para scripts más complicados necesitarás escribirlos como una sola expresión.
result = page . evaluate_script ( <<~JS , 3 , element )
(function(n, el){
var val = parseInt(el.value, 10);
return n+val;
})(arguments[0], arguments[1])
JS
En los controladores que lo admiten, puede aceptar, descartar y responder alertas, confirmaciones y avisos.
Puede aceptar mensajes de alerta envolviendo el código que produce una alerta en un bloque:
accept_alert 'optional text or regex' do
click_link ( 'Show Alert' )
end
También puedes aceptar o descartar una confirmación envolviéndola en un bloque:
accept_confirm 'optional text' do
click_link ( 'Show Confirm' )
end
dismiss_confirm 'optional text' do
click_link ( 'Show Confirm' )
end
También puede aceptar o descartar solicitudes y también proporcionar texto para completar la respuesta:
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
Todos los métodos modales devuelven el mensaje que se presentó. Entonces, puede acceder al mensaje de aviso asignando el retorno a una variable:
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?' )
Puede resultar útil tomar una instantánea de la página tal como está actualmente y echarle un vistazo:
save_and_open_page
También puedes recuperar el estado actual del DOM como una cadena usando page.html .
print page . html
Esto es sobre todo útil para la depuración. Debe evitar realizar pruebas con el contenido de page.html
y utilizar en su lugar los métodos de búsqueda más expresivos.
Finalmente, en los controladores que lo soporten, puedes guardar una captura de pantalla:
page . save_screenshot ( 'screenshot.png' )
O haga que se guarde y se abra automáticamente:
save_and_open_screenshot
Las capturas de pantalla se guardan en Capybara.save_path
, en relación con el directorio de la aplicación. Si ha requerido capybara/rails
, Capybara.save_path
por defecto será tmp/capybara
.
Los ayudantes y comparadores que aceptan selectores comparten una firma de método común que incluye:
Estos argumentos suelen ser opcionales de una forma u otra.
El argumento del nombre determina el selector que se utilizará. El argumento es opcional cuando un asistente transmite explícitamente el nombre del selector (por ejemplo, find_field
usa :field
, find_link
usa :link
, etc.):
page . html # => '<a href="/">Home</a>'
page . find ( :link ) == page . find_link
page . html # => '<input>'
page . find ( :field ) == page . find_field
El argumento del localizador generalmente representa información que puede distinguir de manera más significativa un elemento que coincide con el selector de un elemento que no:
page . html # => '<div id="greeting">Hello world</div>'
page . find ( :css , 'div' ) . text # => 'Hello world'
page . find ( :xpath , './/div' ) . text # => 'Hello world'
Los métodos de búsqueda de propósito general como find
y all
pueden aceptar el localizador como su primer argumento posicional cuando el método puede inferir el valor predeterminado de la configuración de Capybara.default_selector
: