Appium Page Object Model

The Page Object Model (POM) is one is the most commonly used design patterns in Test Automation. It helps to separate each action of the UI elements from the test logic, which makes the code cleaner, reusable, and easier to maintain. 

Here are some of the advantages of POM: 

Avoid code duplication: Write locator code once and reuse it in multiple tests.
Easy maintenance: If a locator changes, you only update it in one place.
Better readability: Test cases become short and easy to understand. 
Logical grouping: Related actions are stored in the same page class.

For more details about POM, read our Selenium POM tutorial.

Below, an example is given for the comparison writing script with and without POM in the Appium TestNG framework in the Appium Project. 

Before getting into the code, to understand how to set up an automation framework in Appium, follow this Selenium - Java Framework Setup. Appium Framework is similar to the Selenium Framework Setup. 

Read our Java TestNG tutorial to get a clear understanding of the TestNG Framework: Java TestNG

Without Page Object Model

Here’s an example of adding an item to the cart in the Sauce Labs demo app without using POM:

@Test
public void test_addToCartWithoutPOM() {
    // Enter the username
    driver.findElement(AppiumBy.accessibilityId("test-Username")).sendKeys("standard_user");
    // Enter the password
    driver.findElement(AppiumBy.accessibilityId("test-Password")).sendKeys("secret_sauce");
    // Click the login button
    driver.findElement(AppiumBy.accessibilityId("test-LOGIN")).click();
    // Click the menu icon
    driver.findElement(AppiumBy.xpath("//android.view.ViewGroup[@content-desc='test-Menu']/android.view.ViewGroup/android.widget.ImageView")).click();
    // Click "All Items"
    driver.findElement(AppiumBy.accessibilityId("test-ALL ITEMS")).click();
    // Add the product to cart
    driver.findElement(AppiumBy.xpath("//android.widget.TextView[@text='Sauce Labs Backpack']/following-sibling::android.view.ViewGroup[@content-desc='test-ADD TO CART']")).click();
    // Click the cart icon
    driver.findElement(AppiumBy.accessibilityId("test-Cart")).click();
}


Problem: The locators and test steps are all mixed together. If any locator changes, you must edit every test where it appears.

With Page Object Model

We’ll create a separate class (ProductPage) to store all the element locators and actions for the product page.

ProductPage.java

package POM.android.page;
import io.appium.java_client.AppiumBy;
import io.appium.java_client.AppiumDriver;
public class ProductPage {
    AppiumDriver driver;
    // Constructor - receives the driver from the test class
    public ProductPage(AppiumDriver driver) {
        this.driver = driver;
    }
    public void enterUserName(String userName) {
        driver.findElement(AppiumBy.accessibilityId("test-Username")).sendKeys(userName);
    }
    public void enterPassword(String password) {
        driver.findElement(AppiumBy.accessibilityId("test-Password")).sendKeys(password);
    }
    public void clickLogin() {
        driver.findElement(AppiumBy.accessibilityId("test-LOGIN")).click();
    }
    public void clickMenuButton() {
        driver.findElement(AppiumBy.xpath("//android.view.ViewGroup[@content-desc='test-Menu']/android.view.ViewGroup/android.widget.ImageView")).click();
    }
    public void clickAllItems() {
        driver.findElement(AppiumBy.accessibilityId("test-ALL ITEMS")).click();
    }
    public void clickAddToCartFromProducts(String item) {
        driver.findElement(AppiumBy.xpath("//android.widget.TextView[@text='" + item + "']/following-sibling::android.view.ViewGroup[@content-desc='test-ADD TO CART']")).click();
    }
    public void clickCartIcon() {
        driver.findElement(AppiumBy.accessibilityId("test-Cart")).click();
    }
}


Test Class using POM

SauceLabProductAndroidTest.java

package POM.android.test;

import POM.android.page.ProductPage;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;

import java.net.MalformedURLException;
import java.net.URL;

public class SauceLabProductAndroidTest {

    AppiumDriver driver;

    @BeforeMethod
    public void startDriver() throws MalformedURLException {
        DesiredCapabilities caps = new DesiredCapabilities();
        caps.setCapability("appium:platformVersion", "14");
        caps.setCapability("appium:deviceName", "emulator-5554"); // Example device name
        caps.setCapability("appium:platformName", "Android");
        caps.setCapability("appium:appPackage", "com.swaglabsmobileapp");
        caps.setCapability("appium:appActivity", "com.swaglabsmobileapp.MainActivity");

        driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), caps);
        System.out.println("Android driver created");
    }

    @Test
    public void test_verifyUserAbleToOrderProduct() {
        ProductPage productsPage = new ProductPage(driver);
        productsPage.enterUserName("standard_user");
        productsPage.enterPassword("secret_sauce");
        productsPage.clickLogin();
        productsPage.clickMenuButton();
        productsPage.clickAllItems();
        productsPage.clickAddToCartFromProducts("Sauce Labs Backpack");
        productsPage.clickCartIcon();
    }

    @AfterClass
    public void tearDown() {
        // Close the app
        if (driver != null) {
            driver.quit();
        }
    }
}



In this script, you can see, how we used the code from ProductPage.java to create a test.

The advantage of the POM model is reusing the same code from ProductPage.java to create multiple tests

Example:

@Test
public void test_addToCart() {
    ProductPage productsPage = new ProductPage(driver);
    productsPage.enterUserName("standard_user");
    productsPage.enterPassword("secret_sauce");
    productsPage.clickLogin();
    productsPage.clickMenuButton();
    productsPage.clickAllItems();
    // Add to cart steps
}
@Test
public void test_submitOrder() {
    ProductPage productsPage = new ProductPage(driver);
    productsPage.enterUserName("standard_user");
    productsPage.enterPassword("secret_sauce");
    productsPage.clickLogin();
    // Submit order steps
}
@Test
public void test_verifyOrder() {
    ProductPage productsPage = new ProductPage(driver);
    productsPage.enterUserName("standard_user");
    productsPage.enterPassword("secret_sauce");
    productsPage.clickLogin();
    // Verify order steps
}

 

Related Tutorials