Emanuil Tolev Emanuil Tolev - 1 year ago 70
Ruby Question

Support for the Page Object pattern in Ruby

In Ruby-land we have Capybara and Webrat to drive our web browsers during functional testing with Cucumber.

What I can't find is something like Geb in Groovy/Java-land which seems like it works on one level of abstraction higher than Capybara. This is the description of Geb from the Geb website.

Geb is a browser automation solution.

It brings together the power of WebDriver, the elegance of jQuery
content selection, the robustness of Page Object modelling and the
expressiveness of the Groovy language.

Capybara already brings together WebDriver (usually Selenium) and jQuery-style content selection. But it doesn't have any support for the Page Object idea. (You create classes to represent the pages under test, so the steps carry out actions upon them rather than look at the DOM directly all the time. Like a mini-API for your page.)

To give an example of the kind of useful feature I'm looking for, I understand from a colleague that Geb can automatically assert that the page under test matches the attributes in the virtual page object which represents the page to your Cucumber tests.

tgf tgf
Answer Source

I've made use of Site Prism for page-objects in a fairly large application. Cheezy's page-object gem was the other gem that I considered at the time but it didn't make use of Capybara (which when used correctly can aid with timing issues). The page-object gem has it's own "wait" mechanism.

There's also another gem but I suspect it's abandoned.

The page-object gem will give you test code along these lines:

class LoginPage
  include PageObject

  page_url "http://example.com/login"
  text_field(:username, :id => 'username')
  text_field(:password, :id => 'password')
  button(:login, :id => 'login')

  def login_with(username, password)
    self.username = username
    self.password = password

# in your tests
visit_page LoginPage do |page|
page.login_with('[email protected]', 'incorrect')
page.wait_until do # using default of 30s for this asynch call
  page.text.include? 'invalid user or password'
expect(page).to have_content 'invalid user or password'

More examples can be seen in this project: https://github.com/JonKernPA/pageobject and on the wiki https://github.com/cheezy/page-object/wiki/Elements

Site Prism looks like this:

class LoginPage < SitePrism::Page
  set_url '/login'

  element :username_field, '#username'
  element :password_field, '#password'
  element :login_button, '#login'

  def login_with(username, password)
    username_field.set username
    password_field.set password
    login_button.click # this uses capybara to find('#login').click

# in your tests
@page = LoginPage.new
@page.login_with('[email protected]', 'incorrect')
# capybara automatically waits for us
expect(@page).to have_content 'invalid user or password'

The Site Prism README has a lot of good examples. Everything else you need to know is in Capybara's excellent README and documentation.

There are of course far more differences than these small example shows.
I would advise you to take a look at both and decide what your requirements are.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download