logo logo

Testing your Ruby Waters with Capybara

Test your Ruby waters with Capybara

We know how helpful it is to have the application test code maintained in the same place as the developed code. Today, there are many alternatives for web-based automation tools, however many people struggle to make that a reality due to various reasons. When creating tests we should aim for tests that are modular, easy to write, and easy to maintain. Tests as expected to give good and fast feedback on code quality in the Agile and TDD environments.

Capybara brings good news to those who have Ruby as the language that is followed for their application codebase. Capybara is a web-based automation testing framework that helps create functional tests which simulate how the users interact with the application. Let us discuss the benefits of using Capybara here.

No Setup is Required

Capybara is a library written in Ruby language. This makes it easy to simulate how a user interacts with your AUT.

Capybara requires Ruby 2.5.0 or later. To install, add this line to your Gemfile and run bundle install:

gem 'capybara'

If you are testing a Rails app, add this line to your test helper file:

require 'capybara/rails'

If the application you are testing is a Rack app, but not Rails, set Capybara.app to your Rack app:

Capybara.app = MyRackApp

Talks with many different drivers.

Very much like Watir, Capybara is a library/gem worked to be utilized on top of a fundamental web-based driver. You can seamlessly choose between Selenium, Webkit, or pure Ruby drivers.

If you need to test JavaScript, or if your app interacts with (or is located at) a remote URL, you’ll need to use a different driver. If using Rails 5.0+, but not using the Rails system tests from 5.1, you’ll probably also want to swap the “server” used to launch your app to Puma in order to match Rails defaults.

Capybara.server = :puma # Until your setup is working
Capybara.server = :puma, { Silent: true } # To clean up your test output

Here are some of the web drivers supported by Capybara:

  • rack::test:
    It uses the rack::test driver by design. This driver is much faster than other drivers, but it doesn’t support JavaScript and can’t access HTTP resources outside of the application for which the tests are written (Rails app, Sinatra app).
  • selenium-webdriver:
    Capybara is compatible with selenium-webdriver, a web-based automation system. It supports JavaScript, can access HTTP resources outside of the program and can be configured for headless testing, which is particularly useful in CI scenarios. To make use of this driver, you’ll need to do the following:

    Capybara.default_driver = :selenium
  • capybara-webkit:
    The capybara-webkit driver can be used for true headless testing with JavaScript support (gem). It makes use of QtWebKit and is much faster than Selenium because it does not load the entire browser. To make use of this driver, you must first add:

    Capybara.default_driver = :webkit

This means, your tests run against from fast headless mode to an actual browser with no changes to your tests.

Offers a user-friendly Domain-Specific Language

Capybara provides an intuitive API that mimics the language an actual user would use. The DSL (Domain Specific Language) is used to describe the actions executed by the web driver. Capybara tries to locate the relevant element in the DOM and execute the action, such as click button, enter text, etc., when the page is loaded using the DSL (and web driver). This gives Capybara the possibility to pair with Cucumber for BDD, RSpec, Test::Unit, Minitest, and  Minitest::Spec.

Capybara can only locate visible elements by default. Since a real user will be unable to communicate with non-visible components, this is the case.
In Capybara, all searches are case-sensitive. Capybara heavily relies on XPath, which does not help case insensitivity.

  • Navigation
    If you use a spec_helper you can mention the host in the Capybara properties.Capybara.default_driver = :selenium_chrome
    Capybara.app_host ='https://google.com'
    Then use visit to navigate.visit '/'
  • Click link/button
    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')
  • Text Field
    fill_in('First Name', with: 'John')
  • Radio Button
    choose('A Radio Button')
  • CheckBox
    check('A Checkbox') uncheck('A Checkbox')
  • Dropdown
    select('Option', from: 'Select Box')
  • Upload File
    attach_file('File', '/path/to/image.jpg')

Finders

If you ever need to locate a button in order to click on it, but the method click_button isn’t enough, or if you need to find the value entered into a textbox, or find a piece of text inside another segment, Capybara has a variety of Finders built-in.

  • find_field
  • find_link
  • find_button
  • find by xpath [find(:xpath)]
    To use XPath selectors, change this configuration value:

    Capybara.default_selector = :xpath

    The selector type can be specified, if necessary:

    find(:xpath, 'actual_xpath'

Matching to avoid Ambiguity

At your disposal are two options, Capybara.exact and Capybara.match.

Exactness

Capybara.exact and the exact option work together with the is expression inside the XPath gem. When exact is true, all is expressions match exactly, when it is false, they allow substring matches. Many of the selectors built into Capybara use the is expression. This way you can specify whether you want to allow substring matches or not. Capybara.exact is false by default.

click_link("Password") # also matches "Password confirmation" 
Capybara.exact = true 
click_link("Password") # does not match "Password confirmation" 
click_link("Password", exact: false) # can be overridden
Strategy

Using Capybara.match and the equivalent match option, you can control how Capybara behaves when multiple elements all match the locator. There are four different strategies allowed by Capybara:

  1. first: Just picks the first element that matches.
  2. one: Raises an error if more than one matching element is found.
  3. smart: If exact is true, raises an error if more than one matching element is found, just like one. If exact is false, it will first try to find an exact match. An error is raised if more than one element is found. If no elements are found, a new search is performed which includes partial matches. If that search also returns multiple matches, an error is raised.
  4. prefer_exact: If multiple matches are found, some exact, and some not, then the first exact match is returned.

The default for Capybara.match is :smart. To emulate the behavior in Capybara 2.0.x, set Capybara.match to :one. To emulate the behaviour in Capybara 1.x, set Capybara.match to :prefer_exact.

DSL also supports other frequently used actions such as Querying, Scoping, Working with windows, Scripting and Modals.

Tackle the asynchronous web with powerful synchronization

Capybara will never have you manually wait for asynchronous processes to complete. This means you can forget all those nasty explicit waits.

Capybara has an internal mechanism for handling asynchronous loading of parts of the page. A good example is clicking on some part of the page that causes JavaScript to be executed and creates a new element on the page.

click_link('hello') 
click_link('world')

Let’s pretend that clicking the link ‘hello’ initiates an asynchronous process, such as an Ajax request, that adds the link ‘world.’ Since the relation does not yet exist, the second argument is likely to fail.

Capybara, on the other hand, has a method for dealing with these circumstances that allows it to retry locating the element for a short period of time before throwing a mistake. The default time is 2 seconds, but this can be changed.

There is no one-size-fits-all solution to these problems. On the one hand, it’s a good idea to keep the wait mechanism’s ambiguity secret from the test script’s author so that the syntax is simpler and easier to understand. On the other hand, getting more leverage over the wait process and managing it yourself is often preferable.

In any case, the script’s unexpected failures are often caused by this wait problem. This is most likely a sign that the implementation is experiencing performance or other problems.

Capybara also supports JavaScript execution via:

page.execute_script()

where JavaScript code can be passed like this:

page.execute_script("$('#area button.primary').click()")

Visual regression testing with Capybara

In drivers that support it, you can save a screenshot:

page.save_screenshot('screenshot.png')

Screenshots are saved to Capybara.save_path, relative to the app directory. If you have required capybara/railsCapybara.save_path will default to tmp/capybara.

Percy Capybara lets you take all the time you’ve spent building your feature tests and expand them with screenshots and visual regression tests to cover all the visual changes in your app, even behind complex UI states.

Let Capybara test-swim into your Ruby waters

Therefore, if Ruby is the language used in your application don’t think twice but jump into using Capybara for automation testing as it has a very supportive DSL that saves time in grabbing those elements and it works with the popular test frameworks like CucumberRSpec, and Minitest. Therefore, let this be a start of having the tests in the same code base as your application and reap all the benefits that Capybara has to deliver. Good Luck!

Christina Thalayasingam

About the author

Christina Thalayasingam

Christina Thalayasingam has more than 7 years of experience in both functional and non-functional testing. She possesses a development background. Since she has worked on PHP Web Development and Android Mobile Development before taking up Quality Engineering. She has worked in automate testing content management systems for the UK government, point of sales applications, eCommerce applications, and clinical trial applications. She has worked on-site in the UK on projects with the UK government sector and major food supply chain management companies. Christina is currently working as a Test Engineering Manager at NorthWestern Mutual a Fortune100 Financial services company, where she is managing the testing effort for their Customer Experience Web Applications, which comprises of micro services and micro applications.  Also, she has been part of various prestigious conferences, technical meetups, and webinars. She is a software testing evangelist.

Join TestProject Community

Get full access to the world's first cloud-based, open source friendly testing community. Enjoy TestProject's end-to-end test automation Platform, Forum, Blog and Docs - All for FREE.

Join Us Now  

Leave a Reply

popup image

Become a master for Selenium testing

Getting started with web testing? We’ve got you covered with a FREE ready-to-go test automation platform that’s already bundled up with Selenium to simplifying and enhancing your experience.
Get Started
FacebookLinkedInTwitterEmail