Page Objects in Selenium 2.0

So you’ve written your first Selenium 2.0 test, but is that really the right way to build tests? In the second article in this series we’ll look at the difference between test specification and test implementation and how Selenium achieves this with page objects.

Specification vs Implementation

There’s an important difference in tests between the specification of what to test versus the implementation of how to test.

For example, my test specification might be “When the user enters their username and password and clicks the login button, then they are logged in and can see their recommendations”. This describes a scenario – it’s a specification of what the test should do. However, the test implementation has to deal with things like:

The username field is named “f_username”

The password field is named “f_password”

The login button is found via the CSS “#loginButton input”

If I change the layout of my login page, does the specification change? Hell no – I still need to provide credentials and click the login button. But has my implementation changed? Almost certainly!

Separating test specification from test implementation makes tests more robust. If I change how login works, I don’t want to have to change every single test that needs a logged in user – there’s probably a few of them! Instead, I only want to change the implementation – which fields to use, which buttons to press – in a single, common location.

Using Page Objects

In Selenium, you can separate specification from implementation by using page objects. That is, unlike in our previous example where the test code is littered with implementation details (how to find the keyword field or how to find the submit button), instead we move this logic into a page object.

If we built a page object to represent the Amazon home page, what would it look like?

This is a pretty neat specification for our test: given a user on the amazon home page, when the user searches for ‘iain banks’, then the title of the top result is ‘Transition’.

There’s no implementation details in our test now. If any of the implementation details around searching change – we only need to change our page object. This is particularly important when the page objects are reused by multiple tests. Instead of having to manually change dozens of tests, we make our change in a single location – the page object.

Implementing Page Objects

By removing the implementation details from the test, they now sit within the page object. So how could we implement the page object interfaces we defined above? We could simply reuse the logic we had in our tests previously:

However, Selenium gives us another way to do this – we can also define the web elements declaratively, by using annotations. Although either approach is valid, using annotations tends to be neater. So let’s have a look at the top of the homepage class now:

On lines two and three we type in our search term to the field we declared above and then click the go button. But what on earth is happening on lines four and five? This piece of magic – the PageFactory – is what allows us to use annotations to declare our elements.

Page Factory

The page factory instantiates our page object (AmazonSearchResultsPage) and finds the annotated fields. The fields are then initialised to the associated elements on the page. This is how we’re able to simply use the fields without having to initialise them. The returned search results page is then a fully populated page object, ready to be used by the test as before.

There’s one more method to see on the homepage – the navigateTo method. This also uses the page factory – this time to initialise our AmazonHomePage.

And there we have it – a better amazon search example – now using page objects and annotations. This is a much better way to structure tests than having implementation and specification intermingled within the test.

As before, all the examples are available on github. This article was part 2 in a series, if there’s a specific aspect of using Selenium you’d like to see covered in a future article let us know in the comments below.

I’m trying to navigate to a particular iframe, and I could not get the whole source of the web app, as the view source is blocked, and i could find the source only for this particular iframe. Can you please advise me how to go about navigating to this particular iframe, and get hold of the elements in it ? Because, the elements in that iframe are not invisible to webdriver, and it keeps on giving messages that the specified element does not exist.

I’m calling switchTo(“frame”), and then trying to find the element in that iFrame. But the execute method in the webdriver is passing me a Status Code “7”: which means “NoSuchElement An element could not be located on the page using the given search parameters.” (See: http://code.google.com/p/selenium/wiki/JsonWireProtocol#Response_Status_Codes). But my element is clearly there in that iFrame. Can you pls suggest any debugging techniques, so that I can move forward ?

Hi Vishal – glad you got the original problem sorted. Not sure why clicking on it wouldn’t work. Are you getting an error when you call click()? There’s probably something specific about your case, I’m afraid. Without seeing much more detail I can’t really guess as to what might be going wrong.

I’m not getting any error when i do a click. I modified the click() method to give me a return code, and it is 0, which says sucess. But however it is not clicking the span id. In my above post I’ve included the html tag, but I think this site is not allowing to post html tag content. Below is the content before clicking the element:

Is there some javascript firing when you click the span? I don’t see an onclick or anything. Whatever is updating the css class obviously isn’t being triggered by webdriver, so it depends what actually triggers it, because it doesn’t look like its the element itself.

Are you familiar with any design patterns that would help in, say, a few pages with the same header/footer that you’d like to interact with? Say the Sign-in/out ability is on every page throughout the session as a header. I want to be able to sign out of my session from any of those pages. I’ve thought about creating a generic page with the header and footer elements only and extend (Java) from there but I’m not sure the page elements can be instantiated that way. Any thoughts are welcome!

I think I’ve used inheritance for this situation in the past. I can’t remember offhand whether the annotations work in derived classes – but you’d certainly hope so. One to try as it definitely sounds like the right approach.

Even if the annotations don’t work, accessing the page elements in code in derived classes is still worth the benefit of having a single place where common page elements are defined.

Thanks for that great article.
But still got a question: Is it possible to tell the PageFactory not to tell the std constructor but a handmade one (including parameters).
Do you have a workaround?
I would appreciate it if you could give me a hint

Hi Frank,
It looks like you can use PageFactory.initElements(…) to sort out the annotated fields in an already constructed object. So for example, you could manually construct your page object with some complex constructor call, then call initElements(…) to setup the fields.

Can we also place all the web-elements in some another separate file, what do you say is it better to place all the elements on some separate file like property file. Or it is better be place in the Page object.

Hi, PageFactory.initElements only creates a Page object of the required type, with it’s fields initialised. The goButton.click() call actually moves the browser to a new page. So first you execute an action that moves to a new page, then you create a page object to allow your tests to interact with the new page.

Your “Test Implementation” sounds very similar to the idea of a page object. The idea is to separate how to drive the page from what, logically, the test wants to do. E.g. the difference between how to locate the username field in the HTML, vs what you want to see in the test “login with username X”. Page objects are one just pattern for doing that.

Hi David,
Very nice explanation. I had one question regarding PageFactory web element initialization. How should we select the web elements that needs to be initialized? For example, my page might have many page elements out of which I might just use a few at any point or instance. So should I just initialize the main web elements in the page and Lazy initialize i.e find element as and when required?

I don’t see why you wouldn’t normally initialise all the page elements in one go, unless you’ve got hundreds – in which case you’ve got other problems! There are cases where page elements aren’t available all at the same time (e.g. a dynamic, javascript heavy site), in which case you have to be more selective about what to initialise when.

Thanks for the post. Can we data drive the page object design pattern? I tried Hybrid frame work with page objects. It work fine for single set of data and the same fails for group of data.

My framework is little different. All my test statements are in one excel file and test data in another excel file. Can you give me any mail id (I do not have any of the 3 accounts given below)so that i can send the sample project,

Honestly, I wouldn’t use the excel-driven approach. I’ve seen it done and its not great, the details of *what* you’re testing are completely obscured. Hire developers, let them write tests. If you have a QA team that only want to work in Excel, fire them.

Hmm, interesting. I’m not sure I’d agree with using inheritance (always) in this case. Especially when you have different types of pages and different sets of common elements: it might be more flexible to favour composition over inheritance.

Thanks, David. Point taken. In my blog post I mentioned other strategies for Ruby and Python, and should have preferred a different one even for C#. I’ve revised my code already, and will make some sort of change in my blog post.