---
title: Page Object Model (POM) and Page Factory with Appium
description: Learn more about the Page Object Model and how to use it with Appium.
source_url:
  html: https://testingbot.com/resources/articles/page-object-model-appium
  md: https://testingbot.com/resources/articles/page-object-model-appium.md
---

![Page Object Model (POM) and Page Factory with Appium](https://testingbot.com/assets/resources/articles/18.webp)

# Appium and Page Object Model

Learn more about the Page Object Model and how to use it with Appium.

By [Jochen D.](https://testingbot.com/about/jochen-d)2022-06-23

 Share on Facebook 

 Share on Twitter 

 Post on Reddit 

 Share link 

The Page Object Model, also known as POM, is a design pattern in Selenium and Appium that creates an object repository for storing all web elements. It provides cleaner test code, separation of concerns and reduces overall code duplication.

The Page Object Model principle keeps locators and test login separately from each other.

A single Page Object is an instantiation of an object-orientated class, describing locators on a specific page (or view) and its interactions.

## Table of Contents

- [What are the advantages of using Page Object Model?](https://testingbot.com#advantages)
- [POM example](https://testingbot.com#example)
- [How can I use the Page Factory with Appium?](https://testingbot.com#pagefactory)
- [What are the different locator strategies that are used for @FindBy?](https://testingbot.com#difference)
- [When should I use the CacheLookUp annotation with PageFactory?](https://testingbot.com#cachelookup)

## What are the advantages of using Page Object Model?

There are several advantages to using the Page Object Model design pattern.

- **Improves code maintenance:** All locators for a specific flow are grouped together in a specific POM. If a page or application changes its UI, you no longer need to modify all your tests scattered with locators. Simply change it in the page object model.
- **Encourages code reuse:** There is no need to write the same logic across different tests. For example, no need to keep doing the same log in flow if your test requires a logged-in state. Keep all logic for a specific page or action in its own POM file.
- **Improves code readability:** You can find where specific test code is located more easily. If a specific change is required, you can do it in the appropriate file. You no longer need to modify several files for a change in one specific test logic.

## POM Example

A good example of a Page Object Model would be the Login Page Object.   
 This will be responsible for typing in the username and password, and proceeding with the actual login.   
 Other test cases can use this POM when a logged-in state is required.

```java
package com.testingbot.example;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
import io.appium.java_client.android.AndroidKeyCode;
import io.appium.java_client.pagefactory.AndroidFindBy;
import io.appium.java_client.pagefactory.AppiumFieldDecorator;
import org.openqa.selenium.support.PageFactory;
public class LoginPage {
    private AndroidDriver<AndroidElement> driver;
    public LoginPage() {
    }
    public LoginPage(AndroidDriver<AndroidElemen>> driver) {
        this.driver = driver;
    }
    By keyboard = By.className("UIAKeyboard");
    By userNameElement = By.id("userName");
    By passwordElement = By.id("password");
    By loginElement = By.id("login");

    public boolean isDisplayed() {
        return loginElement.isDisplayed();
    }
    public void typeUserName(String name) {
        userNameElement.sendKeys(name);
    }
    public void typePassword(String password) {
        passwordElement.sendKeys(password);
    }
    public void clickLogin() {
        loginElement.click();
    }
    public void hideKeyboardIfVisible() {
        if (keyboard != null) {
            driver.pressKeyCode(AndroidKeyCode.KEYCODE_ESCAPE);
        }
    }
    public void login (String name, String password) {
        hideKeyboardIfVisible();
        typeUserName(name);
        typePassword(password);
        clickLogin();
    }
}
```

This is an example of a Login Page Object Model. The `login` method will be responsible for several things. It will hide the soft keyboard, type in a username, a password and submit.

This is logic that may be used by several other test cases that require a logged in state.

Of course, you can implement Page Object Model in any programming language; Java, Kotlin, Swift, ...

## How can I use the Page Factory with Appium?

You can use [Selenium's PageFactory](https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/PageFactory.html) class with Appium and POM.   
 The PageFactory class can be used with `initElements` to initialize all elements located by the `@FindBy` (or `AndroidFindBy`) annotation.   
 PageFactory will automatically assign the elements to your Page Object Model.

```java
package com.testingbot.example;
import io.appium.java_client.MobileBy;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
import io.appium.java_client.android.AndroidKeyCode;
import io.appium.java_client.pagefactory.AndroidFindBy;
import io.appium.java_client.pagefactory.AppiumFieldDecorator;
import org.openqa.selenium.support.PageFactory;
import java.util.concurrent.TimeUnit;

public class ExamplePage {
    private AndroidDriver driver;
    public ProfilePage() {
    }
    public ProfilePage(AndroidDriver driver) {
        this.driver = driver;
        PageFactory.initElements(new AppiumFieldDecorator(driver), this);
    }
    @AndroidFindBy(className = "UIAKeyboard")
    private AndroidElement keyboard;
    @AndroidFindBy(id = "userName")
    private AndroidElement userNameElement;
    @AndroidFindBy(id = "password")
    private AndroidElement passwordElement;
    @AndroidFindBy(id = "login")
    private AndroidElement loginElement;
    public boolean isDisplayed() {
        return loginElement.isDisplayed();
    }
    public void typeUserName(String name) {
        userNameElement.sendKeys(name);
    }
    public void typePassword(String password) {
        passwordElement.sendKeys(password);
    }
    public void clickLogin() {
        loginElement.click();
    }
    public void hideKeyboardIfVisible() {
        if (keyboard != null) {
            driver.pressKeyCode(AndroidKeyCode.KEYCODE_ESCAPE);
        }
    }
    public void login (String name, String password) {
        hideKeyboardIfVisible();
        typeUserName(name);
        typePassword(password);
        clickLogin();
    }
}
```

There are various annotations which you can use for declaring elements:

- **@FindBy**  

PageFactory will automatically assign elements annotated with `@FindBy`, skipping the requirement of using `driver.findElement()`

- **@FindBys**  

Use more than 1 criteria to locate elements, using an `AND` condition; all criteria must be met. It uses nested `@FindBy` annotations to locate an element.

```java
@FindBys({
 @FindBy(id = "form"),
 @FindBy(name = "username")
})

FormUserNameButton;
```

- **@FindAll**  

Similar to `@FindBys` but uses an `OR` condition; at least one criteria must be matched.

```java
@FindAll({
 @FindBy(id = "form"), // does not match
 @FindBy(name = "username")
})

FormUserNameButton;
```

- **@CacheLookUp**  

Can be used to keep specific elements in memory. If your tests use a specific element frequently, you might see a small speedup using this.

```java
@CacheLookUp
@FindAll({
 @FindBy(id = "form"),
 @FindBy(name = "username")
})

FormUserNameButton;
```

## What are the different locator strategies that are used for @FindBy?

FindBy uses the same locator strategies as the `findElement()` method used in POM.

- `id`
- `name`
- `className`
- `xpath`
- `css`
- `tagName`
- `linkText`
- `partialLinkText`

## When should I use the CacheLookUp annotation with PageFactory?

Using the `@CacheLookUp` annotation has both its advantages and disadvantages.

If you are looking up an element frequently during your tests, and the elements are static without ever changing, then it might be beneficial to use CacheLookup. It will improve the overall test execution.

The disadvantage of using this annotation is when the element does change, you may end up with a `StaleElementReferenceException`. If the element is dynamic and bound to change during the test, do not use the CacheLookUp annotation.

## Sidebar

### TestingBot Cloud Testing

Run automated, manual and visual tests on remote browsers and devices. Sign up for a free trial.

[Free Trial](https://testingbot.com/users/sign_up)

### Latest articles

[![Getting Started with Appium](https://testingbot.com/assets/resources/articles/17-0f1ccf4b98b8ad7a8deb4040a2d3f04ef1131418471be27b1c7d0b1b758880eb.webp)](https://testingbot.com/resources/articles/getting-started-with-appium)

#### [Getting Started with Appium](https://testingbot.com/resources/articles/getting-started-with-appium)

Learn how to use Appium for automated testing

[Read article →](https://testingbot.com/resources/articles/getting-started-with-appium)

[![Getting Started with IntelliJ and Selenium WebDriver](https://testingbot.com/assets/resources/articles/16-511fdda6b13b4e7660736fb97eb23be9b62874f39294870fb66212303d530cca.webp)](https://testingbot.com/resources/articles/getting-started-with-webdriver-in-java-using-intellij)

#### [Getting Started with IntelliJ and Selenium WebDriver](https://testingbot.com/resources/articles/getting-started-with-webdriver-in-java-using-intellij)

A brief overview on how to setup, configure and run Selen...

[Read article →](https://testingbot.com/resources/articles/getting-started-with-webdriver-in-java-using-intellij)

[![Internationalization testing of websites and mobile apps](https://testingbot.com/assets/resources/articles/15-4127c39c1b9ffddd30ae0a465903d841df9fbbd87f39dbef0f260ab101340123.webp)](https://testingbot.com/resources/articles/internationalization-testing)

#### [Internationalization testing of websites and mobile apps](https://testingbot.com/resources/articles/internationalization-testing)

Learn more about Internationalization Testing: how to pre...

[Read article →](https://testingbot.com/resources/articles/internationalization-testing)

## Other Articles

[![Getting Started with Appium](https://testingbot.com/assets/resources/articles/17-0f1ccf4b98b8ad7a8deb4040a2d3f04ef1131418471be27b1c7d0b1b758880eb.webp)](https://testingbot.com/resources/articles/getting-started-with-appium "Getting Started with Appium")

### [Getting Started with Appium](https://testingbot.com/resources/articles/getting-started-with-appium)

Learn how to use Appium for automated testing. We will provide some tips and tricks, performance optimizations and ways to use Appium Inspector to troubleshoot your native mobile app testing.

[Read article →](https://testingbot.com/resources/articles/getting-started-with-appium)

[![Getting Started with IntelliJ and Selenium WebDriver](https://testingbot.com/assets/resources/articles/16-511fdda6b13b4e7660736fb97eb23be9b62874f39294870fb66212303d530cca.webp)](https://testingbot.com/resources/articles/getting-started-with-webdriver-in-java-using-intellij "Getting Started with IntelliJ and Selenium WebDriver")

### [Getting Started with IntelliJ and Selenium WebDriver](https://testingbot.com/resources/articles/getting-started-with-webdriver-in-java-using-intellij)

A brief overview on how to setup, configure and run Selenium WebDriver tests with IntelliJ IDEA.

[Read article →](https://testingbot.com/resources/articles/getting-started-with-webdriver-in-java-using-intellij)

[![Internationalization testing of websites and mobile apps](https://testingbot.com/assets/resources/articles/15-4127c39c1b9ffddd30ae0a465903d841df9fbbd87f39dbef0f260ab101340123.webp)](https://testingbot.com/resources/articles/internationalization-testing "Internationalization testing of websites and mobile apps")

### [Internationalization testing of websites and mobile apps](https://testingbot.com/resources/articles/internationalization-testing)

Learn more about Internationalization Testing: how to prepare and test your website or mobile app for different regions in the world.

[Read article →](https://testingbot.com/resources/articles/internationalization-testing)

[![Visual Testing with Playwright](https://testingbot.com/assets/resources/articles/14-f3f2e8954c8a47cf0bb29059b44f4d2f40998442e22db6f8acdccb8e5b34d8c1.webp)](https://testingbot.com/resources/articles/playwright-visual-regression-testing "Visual Testing with Playwright")

### [Visual Testing with Playwright](https://testingbot.com/resources/articles/playwright-visual-regression-testing)

Playwright provides automated browser testing. It offers a built-in feature to perform visual regression testing for your website.

[Read article →](https://testingbot.com/resources/articles/playwright-visual-regression-testing)

## Ready to start testing?
[Start a free trial](https://testingbot.com/users/sign_up)
