Objective
To explain
page object pattern and how to use it with
jbehave web(3.4.3) and
WebDrive.
A sample project is uploaded in
github. It is simple enough to use as a startup project.
The implementation was done following
this article. The basic is explained there, so in my post I will discuss about the
page object pattern, which simplifies the
web drive implementation.
Page object pattern
|
Each page has a one to one mapping with a java class |
This might seem to be obvious to map all the pages with a java class. And the navigation from one page to another to map to a method of one object that returns the navigation page object. This approach increases readability in a great extant. Now look at a sample code(just to get an idea).
public class BasicWebSteps {
private final Pages pages;
public BasicWebSteps(Pages pages) {
this.pages = pages;
}
@Given("user is on Home page")
public void userIsOnHomePage(){
pages.homePage().open();
}
@When("user clicks on Resume from menu")
public void userClicksOnResumeLink(){
pages.resumePage().open();
}
@Then("Resume page is shown")
public void runStoryPageIsShown(){
pages.resumePage().assertShown();
}
}
This increases the readability of the step definition. It encapsulates the logic of navigation, structure of page specific html, page specific assertions for each pages in corresponding classes. This approach follows Single Responsibility Principle and makes a logical separation in the test project.
Jbehave help you to implement this pattern by providing
WebDriverPage. So your parent class of each page might look like,
public abstract class AbstractPage extends WebDriverPage {
public AbstractPage(WebDriverProvider driverProvider) {
super(driverProvider);
}
...
}
And a simple page can be like the following.
/*
* Contains page specific
* HTML structure
* Assertions
* Navigation
*/
public class ResumePage extends AbstractPage {
public ResumePage(WebDriverProvider driverProvider) {
super(driverProvider);
}
public void open(){
findElement(By.linkText("Resume")).click();
}
public void assertShown() {
String output = findElement(By.cssSelector("#menu .selected a")).getText();
assertTrue("Resume menu should be selected", output.contains("Resume"));
}
}
Use annotation
Use jbehave annotation to simplify the code.
public class LoginPage extends AbstractPage {
@FindBy(how = How.NAME, using = "username")
private WebElement userNameElem;
@FindBy(how = How.NAME, using = "password")
private WebElement passwordElem;
@FindBy(how = How.NAME, using = "role")
private WebElement roleElem;
@FindBy(how = How.NAME, using = "B3")
private WebElement submitButton;
public void loginAs(String profileName) {
User user = User.getUser(profileName);
userNameElem.sendKeys(user.getUserName());
passwordElem.sendKeys(user.getPassword());
roleElem.sendKeys(user.getRole());
submitButton.submit();
}
}
Sample project
The sample project can be found
here.
References