Capybara는 실제 사용자가 앱과 상호 작용하는 방식을 시뮬레이션하여 웹 애플리케이션을 테스트하는 데 도움을 줍니다. 테스트를 실행하는 드라이버에 대해 독립적이며 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'
테스트 중인 애플리케이션이 Rack 앱이지만 Rails가 아닌 경우 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
등).
다음 줄을 추가하여 RSpec 3.5+ 지원을 로드합니다(일반적으로 spec_helper.rb
파일에):
require 'capybara/rspec'
Rails를 사용하는 경우 Capybara 사양을 spec/features
또는 spec/system
에 넣고(RSpec에서 구성한 경우에만 작동) Capybara 사양이 다른 디렉터리에 있는 경우 다음 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
옵션을 제공하여 하나의 특정 드라이버로 전환하세요. 예를 들어:
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
의 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 ( '/projects' )
visit ( post_comments_path ( post ) )
방문 메소드는 단일 매개변수만 사용하며 요청 메소드는 항상 GET입니다.
탐색 세션의 현재 경로를 가져오고 have_current_path
일치자를 사용하여 테스트할 수 있습니다.
expect ( page ) . to have_current_path ( post_comments_path ( post ) )
참고 : current_path
값을 직접 테스트하여 현재 경로를 어설션할 수도 있습니다. 그러나 have_current_path
일치자를 사용하는 것은 이전 작업(예: click_link
)이 완료되었는지 확인하기 위해 Capybara의 대기 동작을 사용하므로 더 안전합니다.
전체 참조: Capybara::Node::Actions
링크와 버튼을 따라 웹앱과 상호 작용할 수 있습니다. 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 }
참고 : find
Ajax 섹션에서 설명한 대로 요소가 페이지에 나타날 때까지 기다립니다. 요소가 나타나지 않으면 오류가 발생합니다.
이러한 요소에는 모두 사용 가능한 모든 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' ) ;
더 복잡한 스크립트의 경우 하나의 표현식으로 작성해야 합니다.
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
모든 모달 메소드는 표시된 메시지를 반환합니다. 따라서 반환 값을 변수에 할당하여 프롬프트 메시지에 액세스할 수 있습니다.
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
로 설정됩니다.
선택기를 허용하는 도우미와 일치자는 다음을 포함하는 공통 메서드 서명을 공유합니다.
이러한 인수는 일반적으로 어떤 방식으로든 선택 사항입니다.
이름 인수는 사용할 선택기를 결정합니다. 도우미가 선택기 이름을 명시적으로 전달하는 경우 인수는 선택 사항입니다(예: 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
구성에서 기본값을 유추할 수 있는 경우 첫 번째 위치 인수로 로케이터를 허용할 수 있습니다.