Embracing Capybara

Preview:

DESCRIPTION

Capybaras are the largest rodents in the world. They are related to guinea pigs, but are the size of a big dog or small pig. They live in South America, and they're pretty damn cute. Capybara is also the name of a Ruby gem written by Jonas Nicklas. It helps you write integration tests for web apps by pretending to be a user with a web browser. It takes a black box approach to testing, letting you go to URLs, click links and buttons, fill in forms, and check that the rendered page contains what you think it should have in it. This talk is about Embracing Capybara: how to understand Capybara, train it to do new tricks, and discipline it when it misbehaves.

Citation preview

Embracing Capybara

Who Has Used Capybara?

Who Has Been Bitten By Capybara?

TimMoore

tmoore

What’s a Capybara?

World’s Largest Rodent!

“Makes it easy to simulate how a user interacts with your application”

http://git.io/capybara

Capybara Anatomy

Browsing DSL

Matchers/Selectors

Browser Engines

visit '/sessions/new' within("#session") do fill_in 'Login', with: 'user@example.com' fill_in 'Password', with: 'password' end click_link 'Sign in' expect(page).to have_content 'Success'

Understanding Capybara

Capybara is Patientvisit '/sessions/new'

within("#session") do fill_in 'Login', with: 'user@example.com'

fill_in 'Password', with: 'password'end

click_link 'Sign in'

expect(page). to have_content 'Success'

Waits for page to load

Capybara is Patientvisit '/sessions/new'

within("#session") do fill_in 'Login', with: 'user@example.com'

fill_in 'Password', with: 'password'end

click_link 'Sign in'

Capybara.using_wait_time(60) do expect(page). to have_content 'Success'end

Waits for page to load

Capybara is Patientvisit '/sessions/new'

within("#session") do fill_in 'Login', with: 'user@example.com'

fill_in 'Password', with: 'password'end

click_link 'Sign in'

expect(page). to have_content 'Success', wait: 60

Waits for page to load

Methods that Wait• find(selector), find_field, find_link, etc.

• within(selector) (scoping)

• has_selector?/has_no_selector? & assertions

• form & link actions

• click_link/button

• fill_in

• check/uncheck, select, choose, etc.

Methods that Don’t• visit(path)

• current_path

• all(selector)

• first(selector) (counter-intuitively)

• execute_script/evaluate_script

• simple accessors: text, value, title, etc.

Don’t Do This

click_link('Search') expect(all('.search-result').count). to eq 2

Returns 0Does not wait

Good

click_link('Search') expect(page). to have_css '.search-result', count: 2

Don’t Do This

click_button('Save') expect(find('.dirty-warning').text). not_to contain('Unsaved changes')

Does not wait

Good

click_button('Save') expect(find('.dirty-warning')). to have_no_text('Unsaved changes')

Also Good

click_button('Save') expect(find('.dirty-warning')). not_to have_text('Unsaved changes')

Training Capybara

Don’t Do ThisScenario: Searching for cats Given I am on "/search" When I fill in "input.search_text" with "cats" And I press "Search" Then I should see "grumpy cat" within "div.search-results"

Don’t Do ThisScenario: Searching for cats Given I am on "/search" When I fill in "input.search_text" with "cats" And I press "Search" Then I should see "grumpy cat" within "div.search-results"

“A step description should never contain regexen, CSS or XPath selectors”

“web_steps.rb is a terrible, terrible idea” - Boring scenarios - Brittle scenarios - Where is my workflow?

BetterScenario: Searching for cats Given I am on the search page When I fill in "Search" with "cats" And I press "Search" Then I should see "grumpy cat" within the search results

BestScenario: Searching for cats When I search for "cats" Then I should see "grumpy cat" within the search results

Don’t Do ThisWhen /^I search for "([^"]*)"$/ do |search_text| visit "/search" fill_in "input.search_text", with: search_text click_button "Search" end

BetterWhen /^I search for "([^"]*)"$/ do |search_text| search_page = my_app.search_page search_page.search_input. fill_in search_text search_page.search_button.click end

Betterclass MyAppTester def initialize @session = Capybara::Session.new(:selenium) end !

def search_page MyAppTester::SearchPage.new(@session) end end

Betterclass MyAppTester::SearchPage def initialize(session) session.visit "/search" @session = session end def search_input @session.find "input.search_text" end def search_button @session.find "button.search" end end

BetterWhen /^I search for "([^"]*)"$/ do |search_text| search_page = my_app.search_page search_page.search_input. fill_in search_text search_page.search_button.click end

BestWhen /^I search for "([^"]*)"$/ do |search_text| my_app.search_for search_text end

Don’t Do Thisfind(:css, "div.main div.sidebar div.search div.advanced div.actions button.submit").click

Failure/Error: find(:css, "div.main div.sidebar div.search div.advanced div.actions button.submit").click Capybara::ElementNotFound: Unable to find css "div.main div.sidebar div.search div.advanced div.actions button.submit"

Disciplining Capybara

Setting Breakpoints

When /^I debug$/ do debugger end

Taking ScreenshotsAfter do |scenario| filename = scenario.name.gsub(/\W/, '_') page.save_screenshot( "target/reports/#{filename}.png") end !

http://git.io/capybarascreenshot

Firefox•focusmanager.testmode = true

• Update selenium-webdriver gem

• Disable auto-update in CI

• Beware platform differences

• http://git.io/capybarafirebug

Getting Help

• http://groups.google.com/group/ruby-capybara

• Freenode (IRC): #capybara

• Stack Overflow

Summary• Understand Capybara synchronisation

• Be explicit with Capybara

• Use Page Objects for readable, flexible tests

• Keep selectors simple

• If you get bitten, seek help!

Fix Flaky Tests

Thanks! Any Questions?