Is a page URL a property of the Page Object ? What if a number of different URLs lead to the same page ? Also, what if the URL is used to pass some parameters, do you if at all deal with that ?
Most of my pages don't know (or care) about the URLs that lead to them. When I have pages that I want to jump to directly (rather than navigating to by following links on other pages), I often bundle the knowledge of those URLs into a "site" object or "site navigation" object.
What fields do your page objects have except for WebElements and a WebDriver instance ?
Mostly private static fields (Java) for the locators for the interesting elements on the page.
I don't usually store WebElement objects for use across page operations. Instead, I create fresh ones for each operation. Usually.
My page objects often use a polling DSL to poll for various conditions. So pages generally also hold a poller or default timer that I can use in my poll expressions.
How do you initialize your page objects ? In the constructor? Using a factory method ? Do you use the PageFactory class provided by WebDriver ?
My page object constructors merely stash the WebDriver instance and whatever other parameters they'll need later. I work very hard to make sure my page objects do no real work in their constructors.
I almost always create factory methods that hide the incidental details of calling the constructor. So instead of writing this in my test:
@Test public void disasterRecovery() {
...
new HalPage(webDriver, site, defaultTimer).openThePodBayDoor();
...
}
... I'll write this:
@Ignore("Random failures. Cause unknown. Adaptive AI probably makes recovery unnecessary."
@Test public void disasterRecovery() {
...
hal().openThePodBayDoor();
...
}
private HalPage hal() {
return new HalPage(webDriver, site, defaultTimer);
}
If I find that I'm creating the hal()
factory method all over the place, I'll often move it into a "fixture" base class which provides numerous common factory methods. I'm becoming nervous about this practice, because over time the fixture base class becomes bloated with factory methods.
Another practice that I currently use extensively is to bundle those common page parameters into some kind of "context" object, and hand that around instead of the individual parameters. Lately I'm feeling queasy about this practice, because the context objects tend to collect many disparate objects, which increase coupling and reduces cohesion.
Are your page objects ever responsible for browsing to the appropriate web page or do you depend on an "external force" to do the browsing ? In WebDriver terms, do your objects ever do driver.get("URL") ?
I never have pages that do that. I assign all site navigation responsibility to a "site" or "site navigation" object.
A common pattern with page objects is: When a page operation navigates to another page, the operation will return a new page object that represents the destination page. Lately I prefer not to do this. The practice couples each page to each of its destinations. Instead, when some method invokes a page operation that leads to a new page, I make the invoking method create the page object for destination page.