Awesome Page Objects In Testing

I mentioned page objects in the post about WatirSplash 2. In this post i’m gonna explain what these things exactly are and how to use them.

What Is A Page?

When it comes to automated testing then the page is really nothing else than the page user sees when visiting the website. Any meaningful page consists of different components some of which just show information (e.g. text) others allow interaction (e.g. text fields and buttons). Different pages might also have some shared content like header, search field and footer. One important thing about components is that the result of some interactions is another page.

Let me bring you a concrete example. Let’s look at the Bing’s main page (enough of Google in all examples, alright). You can think of the possible sections (Web, Images, Videos, News and More) as a header. There is also the search field and button. Search button is special since clicking on it changes the current page to results page. Makes sense? Let’s see how to convert that information into WatirSplash Page Objects.

Point Of Having Page Objects

The point of having Page Objects is to have better structured code and keep it DRY in your tests too. This all makes your tests easier to maintain. If you’re a software developer then you care about these things when it comes to production code. Why not to use these good practices in tests also? Page Objects make it all possible. Having Page Objects means that it should be easier to change your tests if the application under test (AUT) changes since you need only one place (ideally) to change. Page Objects also make it very clear where to find existing and put the new code.

Let’s Get Rockin’ With Pages And Objects

Let’s get more concrete. I assume that you have created a WatirSplash 2 project already. If not then follow the instructions in the post about WatirSplash 2 or read everything you need to know straight from the README. Let’s create the Main page first:

This command created us the Main page object and a test for it. The generated file looks like this:

And the test itself is nothing fancy yet:

Let’s add something meaningful to our Main page object like search field and button:

You can use all the familiar Watir methods directly in your Page objects! For the sake of clarity let’s also add Header functionality. To do that we’d just use Ruby’s mixin functionality - the Header module:

And make sure to include it into your page object:

We can now update our main_spec to actually test something:

I made two tests - one for the header and another for the search functionality. Since header should be on every page, i could have taken advantage of the RSpec’s Shared Examples feature, but for the sake of this post’s clarity i didn’t.

The second test is a failing test since there’s no way that Watir’s Button#click will return us a results page object. But hey, i’ve just done a little TDD here! Let’s make it work like we want it to work:

I’ve used the WatirSplash::Page::Base#modify method which takes some object as it’s first argument (here button) and a Hash as a second argument. Hash consists of method name as a key and value as Proc object. In this particular case the code above overrides this particular button’s #click method with my #click, which returns Results page object due to the usage of #redirect_to method. Since #click is already existing method on that button, then it will call the original method (e.g. performs the actual clicking) before calling the defined block. The #modify method does all that by using Ruby’s meta-programming. You can always look at the source itself if you’re more interested in the nitty-gritty details.

Let’s create ourselves a Results page object with the results method. This time, let’s be even cooler and generate more code than we did with the Main page object:

This generated us the Results class with the results method:

Let’s add the #count and #[] methods to our #results object by using #modify again so we could chain method invocations naturally as i’ve written in the search functionality test:

I’m invoking the #results method again to get the Watir::Ul element to execute regular Watir methods on it - in these cases #li and #lis. This neat trick hides the implementation details from the tests and makes the tests even more natural to read.

In Conclusion

That’s it - we have created a few tests using Page Objects functionality in WatirSplash 2! Using Page Objects makes your tests (hopefully) more readable and easier to maintain. I like my implementation when compared to others because it makes your page objects to look really succinct and doesn’t add any additional complex API to learn - you can use already learnt Watir methods as you did before. And the code written to support creating and using these Page Objects is also quite clever and short. I love it! I hope you will too.