Keeping It Dry With Page Objects

Keep it DRY (Don’t Repeat Yourself!)

In this post, I’ll discuss how we use page objects to keep things DRY.

Have you ever had someone in your life that repeats what they’ve said over and over again? Have you ever just wanted to say, “You’ve told me that ten times already!”

For me, that person was my mother! 🙂

When it comes to test code, I feel the same way about repetition. Keep it DRY (Don’t Repeat Yourself!).

Why keep it DRY?

It’s really all about working efficiently. Let’s say for example, all of our tests need to login to the same application. It would be a huge waste of time if every Quality Engineer (QE) had to write login code for each test. And what happens when the login page changes? We would need to go back and refactor thousands of tests, wasting  a significant amount of time. We can be very efficient by using page object classes. When a new QE starts, we point them to the login page object class to help save them from the learning curve.

Let’s move on to the how!

In a page object class, you define elements and the methods that interact with those elements. So instead of scattering repetitive code throughout your tests, you abstract it into classes. Generally, the pattern is to have a page object class for every screen of your application under test (AUT). I’m currently working on a Ruby on Rails project, so I’ll use an example involving RSpec and Capybara frameworks with a Selenium driver and a gem called site_prism.

site_prism – the page object DSL for Capybara

I’ve chosen a gem called site_prism, which is a page object domain specific language (DSL) for Capybara. You can find it on GIThub, and I highly recommend it as it has some great features and is actively supported.

Here’s what I like about site_prism:

  1. You provide the CSS it needs to find an element on your page and it returns the Capybara node element, which allows you to perform any Capybara action on it (set, text, click).
  2. It also has the notion of page sections, which makes scoping easier.

Finally, it comes with built-in methods to do things such as waiting for elements to be visible, verifying whether a page is loaded, etc.

The following is a simple representation of a page object class for a login page using site_prism.Page Objects, site_prism

The Login class (line 14) consists of:

  • The page url
  • A footer section
  • Username
  • Password
  • Login button elements
  • A method that logs the user in (line 22)

Now, here’s an RSpec test that references our Login class:


In this test:

  • Line 6 instantiates our Login class
  • Line 14 checks that the page has a footer section by using one of Site Prism’s built-in methods: have_section
  • Line 18 validates that an element within a section exists. This is another example of a built-in method that Site Prism provides: section.should have_element
  • Line 21 is an example of a Capybara node action – .text
  • Line 28 uses the login method in our page object class

You can see how we use page objects to keep things DRY and work more efficiently. To learn more about site_prism, check out the documentation. 

How do you keep things DRY? Let me know by sharing your comments here on the blog.


  1. Thanks, Donna, for this post. I have some additional thoughts on DRY page objects over at my blog:

Leave a Comment