Selenium doesn’t inherently comes with any feature which provide any object management where we can manage the object information for a page and keep this object information outside the test script. Yes, it’s true, we can write the entire script for a page without a page object model and this could run through. This may state less pain to maintain the script only if we have limited test-cases(say 5-10). Considering if we have thousands of test-cases, is it easy to maintain the test script? We can’t change the whole test-script once the AUT goes certain changes or some modifications (which generally happens down the road).
So if the object info of a page change (the probability of which is higher) as the AUT undergoes changes with different release cycle, the impact of that change on the automation suite level is very high since the object info in the script is hard coded.
Why POM?
POM has nowadays become popular test automation design pattern around the testing industry. POM facilitates as to concentrate on testing the AUT rather than fixing the automation suite (the changed objects) to perform the test. In POM the Object information is managed outside the test script, thus making easy to understand the test script.
Advantages of POM
- It makes ease in maintaining the code (flow in the UI is separated from verification)
- Makes code readable (Methods get more realistic names)
- Makes the code reusable (object repository is independent of test cases)
- The Code becomes less and optimised
Implementation of POM
Let us consider a simple test scenario where we have an app with a login page, an account page and, say, home page.
The scenario be like
- We go to the app url
- Validate the app page is correct (home page)
- We go to the login page and fill the form with a valid id and password
- We validate if the account page opens
Now here we are dealing we three pages the home page, the login and the account page. Accordingly we create 3 POM classes, be like :
- HomePage.java
- LoginPage.java
- MyAccountPage.java
Also we create a test class with the test script and names it as
- TestLogin.java
HomePage.java
package pageModel; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class HomePage { WebDriver driver; By homeHeading = By.xpath("//table//tr[3][@class='heading3']"); By loginButton = By.id("login"); public HomePage(WebDriver driver) { this.driver = driver; } //get the heading (the main heading which is present at the home page) public String getHomeHeading() { String heading = driver.findElement(homeHeading).getText(); return heading; } public HomePage clickLoginButton() { driver.findElement(loginButton).click(); return this; } }
LoginPage.java
package pageModel; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class LoginPage { WebDriver driver; By username = By.id("email"); By password = By.name("email"); By submitButton = By.cssSelector("input[type='submit']"); public LoginPage(WebDriver driver) { this.driver = driver; } public LoginPage usernameAs(String email) { driver.findElement(username).sendKeys(email); return this; } public LoginPage passwordAs(String pass) { driver.findElement(password).sendKeys(pass); return this; } public void submit(){ driver.findElement(submitButton).click(); } }
MyAccountPage.java
package pageModel; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class MyAccountPage { WebDriver driver; // Declaring the xpath for the heading in By class By pageHeading = By.xpath("//table//tr[3][@class='heading3']"); public MyAccountPage(WebDriver driver) { this.driver = driver; } //get the heading (username for which the account belongs to) public String getHeading() { String heading = driver.findElement(pageHeading).getText(); return heading; } }
TestLogin.java
package test; import org.junit.Assert; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import pageModel.*; public class TestLogin { WebDriver driver; @BeforeTest public void setUp() throws Exception { // setting the driver executable for chrome browser String chrome_path = System.getProperty("user.dir")+"/chromedriver"; driver = new ChromeDriver(); // created a new instance for chrome driver driver.manage().window().maximize(); } @AfterTest public void tearDown() throws Exception { driver.quit(); } @Test(priority=1) public void test() throws InterruptedException{ driver.get("http://192.168.1.164:8080/home.html"); // validate if we are at the home page String homeHeading = new HomePage(driver).getHomeHeading() ; Assert.assertEquals(homeHeading, "This is HOMEPAGE", "not at the home page"); // redirect to the login page new HomePage(driver).clickLoginButton(); // fill the login form new LoginPage(driver) .usernameAs("[email protected]") .passwordAs("secret") .submit(); // check if redirected to account page with user name [email protected] String accountHeading = new HomePage(driver).getHomeHeading() ; Assert.assertEquals(accountHeading, "Welcome [email protected] ", "not at the account page"); } }
Now, if the AUT undergoes any change at the login page or at any page we just need to change the page object. Thus we don’t need to change our test script again and again (even for the new release or built). The project structure will look like :
1 comments