Unit 3: Android Native Apps Automation with Appium

CSE379 — Mobile Automated Testing 9 min read

I. Orientation — Native Android Automation

Appium is an open-source automation framework that drives Android applications through the WebDriver protocol. For native Android testing, Appium commonly uses the UiAutomator2 driver to locate interface elements, perform user actions, and inspect application state.

  • Native application: An application built for Android whose interface uses components such as TextView, EditText, Button, and RecyclerView.
  • Appium server: Receives WebDriver commands from test code and forwards them to the Android automation driver.
  • UiAutomator2 driver: Appium’s recommended Android driver; install it with appium driver install uiautomator2.
  • Client library: Provides APIs such as findElement(), click(), sendKeys(), and getText() in Java, Python, or another supported language.
  • Desired capabilities: Describe the test session, including platform, device, application, and automation engine.
  • Element locator: A rule used to identify an interface element from the Android view hierarchy.
  • Test principle: Each test should arrange the application state, perform actions, and assert an observable result.
  • Example session:
JAVA
UiAutomator2Options options = new UiAutomator2Options()
    .setDeviceName("Android Emulator")
    .setApp("/apps/GeneralStore.apk")
    .setAutomationName("UiAutomator2");

AndroidDriver driver =
    new AndroidDriver(new URL("http://127.0.0.1:4723"), options);
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));

II. Element Identification — Locating Android Controls

A. Introduction to Id, Xpath and Accessibility ID locators in App with an example

Locators connect test instructions to elements in the Android view hierarchy.

  • ID locator: Uses an Android resource ID such as com.shop:id/nameField; it is usually fast, readable, and stable.
JAVA
WebElement name = driver.findElement(
    AppiumBy.id("com.shop:id/nameField"));
name.sendKeys("Anita");
  • Accessibility ID locator: Uses the element’s accessibility description, normally exposed through Android’s content-desc attribute.
JAVA
driver.findElement(
    AppiumBy.accessibilityId("Open cart")).click();
  • XPath locator: Selects an element by class, attributes, text, or hierarchy; it is flexible but generally slower and more fragile.
JAVA
driver.findElement(AppiumBy.xpath(
    "//android.widget.Button[@text='LET’S SHOP']")).click();
  • Recommended order:
    1. Prefer a unique resource ID.
    2. Use accessibility ID when a stable content-desc exists.
    3. Use XPath only when stronger attributes are unavailable.
  • Inspection: Appium Inspector displays attributes such as resource-id, text, content-desc, class, clickable, and enabled.
  • Stability rule: Avoid absolute XPath expressions such as /hierarchy/.../android.widget.Button[2]; minor layout changes can break them.

III. Android Interaction — Popups, Collections, and Input

A. How to handle Mobile popups and return list of matching elements on Android app

Android tests must handle both system dialogs and application popups without assuming that an element always exists.

  • Permission popup: Android runtime permission dialogs can be accepted automatically through session configuration.
JAVA
options.setAutoGrantPermissions(true);
  • Explicit permission handling: A visible system button may be selected with UiAutomator.
JAVA
driver.findElement(AppiumBy.androidUIAutomator(
    "new UiSelector().textContains(\"Allow\")")).click();
  • Application popup: Dialog buttons inside the app can be located normally by ID, accessibility ID, or text.
  • Matching collection: findElements() returns every matching element as a List<WebElement>; if none match, it returns an empty list rather than throwing NoSuchElementException.
JAVA
List<WebElement> products = driver.findElements(
    AppiumBy.id("com.shop:id/productName"));

for (WebElement product : products) {
    System.out.println(product.getText());
}
  • Safe optional-popup pattern:
JAVA
List<WebElement> buttons = driver.findElements(
    AppiumBy.id("android:id/button1"));
if (!buttons.isEmpty()) {
    buttons.get(0).click();
}
  • Synchronization: Use WebDriverWait for delayed dialogs instead of fixed sleeps.

B. How to extract the text and enter the information on Mobile Apps with Appium

Appium reads displayed values through element attributes and enters information through keyboard-oriented element commands.

  • Text extraction: getText() returns the displayed text of controls such as TextView and Button.
JAVA
String heading = driver.findElement(
    AppiumBy.id("com.shop:id/toolbar_title")).getText();
assertEquals(heading, "Products");
  • Text entry: sendKeys() enters characters into an editable element.
JAVA
WebElement field = driver.findElement(
    AppiumBy.id("com.shop:id/nameField"));
field.clear();
field.sendKeys("Rahul Kumar");
  • Attribute extraction: getAttribute("text"), getAttribute("checked"), or getAttribute("content-desc") can expose state not adequately represented by getText().
  • Keyboard handling: driver.hideKeyboard() dismisses the software keyboard when it blocks another control.
  • Validation: Read the field after entry and compare it with the expected value when data persistence is part of the requirement.

IV. Shopping Workflow — Features and Form Automation

A. Introduction to App features and test cases to automate

Automation begins by translating application features into independent workflows with observable outcomes.

  • Typical features: Registration form, country selection, gender choice, product catalogue, cart, quantity, checkout, and validation messages.
  • Test-case structure:
    • Precondition: The app is installed and opened on the form screen.
    • Action: The user enters data, selects products, and opens the cart.
    • Expected result: Entered data is accepted, selected products appear, and totals are correct.
  • Priority: Automate stable, repeatable, business-critical paths before visual or highly subjective behavior.
  • Independence: Reset application data or navigate to a known starting state so one test does not depend on another.
  • Assertions: Validate application outcomes, not merely whether Appium successfully clicked an element.
  • Coverage examples: Include valid input, missing mandatory values, multiple products, long lists, and price calculations.

B. Test Case in Filling the form details for shopping

A shopping-form test verifies that valid customer details permit navigation to the product catalogue.

  • Input sequence: Enter the customer name, select gender, choose a country, and press the shopping button.
  • Control selection: IDs should identify fields and buttons; Android UIAutomator can select a scrollable country option.
  • Example:
JAVA
driver.findElement(AppiumBy.id("com.shop:id/nameField"))
      .sendKeys("Meera Shah");
driver.hideKeyboard();

driver.findElement(AppiumBy.id("com.shop:id/radioFemale"))
      .click();
driver.findElement(AppiumBy.id("com.shop:id/countrySpinner"))
      .click();

driver.findElement(AppiumBy.androidUIAutomator(
    "new UiScrollable(new UiSelector().scrollable(true))" +
    ".scrollIntoView(new UiSelector().text(\"India\"))")).click();

driver.findElement(AppiumBy.id("com.shop:id/btnLetsShop")).click();

assertEquals(
    driver.findElement(AppiumBy.id("com.shop:id/toolbar_title")).getText(),
    "Products");
  • Expected result: The catalogue opens only after all mandatory details contain valid values.
  • Reliability: Wait for the catalogue title to become visible before asserting it.

V. Validation — Errors and Monetary Results

A. Verifying toast messages for error validations

A toast assertion verifies transient feedback produced when invalid input prevents an operation.

  • Trigger: Leave a mandatory field empty and immediately submit the form.
  • Toast locator: UiAutomator2 can expose a toast as android.widget.Toast, although it remains visible only briefly.
JAVA
driver.findElement(AppiumBy.id("com.shop:id/btnLetsShop")).click();

WebElement toast = new WebDriverWait(driver, Duration.ofSeconds(3))
    .until(ExpectedConditions.presenceOfElementLocated(
        AppiumBy.xpath("//android.widget.Toast")));

assertEquals(toast.getText(), "Please enter your name");
  • Timing: Locate the toast immediately after the triggering action; unrelated steps can allow it to disappear.
  • Text-specific XPath: //android.widget.Toast[@text='Please enter your name'] combines detection and validation.
  • Outcome assertion: Also verify that the form remains displayed, proving that invalid data did not advance the workflow.

B. Testcase: Validating Total amount generated functionality

Total validation compares the application’s displayed total with the arithmetic sum of selected product prices.

  • Extraction: Read each price label, remove its currency symbol and grouping characters, and convert it to BigDecimal.
  • Calculation: For prices (p_1,p_2,\ldots,p_n), the expected total is:
TEXT
T = p1 + p2 + ... + pn

Here, T is the expected cart total and each p is a selected product price.

JAVA
BigDecimal expected = BigDecimal.ZERO;
for (WebElement price : driver.findElements(
        AppiumBy.id("com.shop:id/productPrice"))) {
    expected = expected.add(new BigDecimal(
        price.getText().replaceAll("[^0-9.]", "")));
}

String totalText = driver.findElement(
    AppiumBy.id("com.shop:id/totalAmountLbl")).getText();
BigDecimal actual = new BigDecimal(
    totalText.replaceAll("[^0-9.]", ""));

assertEquals(0, expected.compareTo(actual));
  • Precision: Use BigDecimal, not double, because binary floating-point can introduce currency rounding errors.
  • Scope: Ensure the price locator targets cart items only and does not accidentally include the total label itself.

VI. Product Catalogue — Scrolling and Dynamic Selection

A. Testcase: Scrolling in product list example with Appium Android scroll

Scrolling enables a test to reach catalogue items that are outside the visible viewport.

  • UiScrollable strategy: Android’s UiScrollable searches a scrollable container until the specified text becomes visible.
JAVA
WebElement item = driver.findElement(AppiumBy.androidUIAutomator(
    "new UiScrollable(new UiSelector().scrollable(true))" +
    ".setMaxSearchSwipes(10)" +
    ".scrollIntoView(new UiSelector().text(\"Air Jordan 4 Retro\"))"));

assertTrue(item.isDisplayed());
  • Bounded search: setMaxSearchSwipes(10) prevents an endless search when the product does not exist.
  • Container awareness: If multiple scrollable views exist, identify the intended RecyclerView by resource ID where possible.
  • Alternative: W3C pointer actions can perform coordinate swipes, but text-based scrolling is usually clearer for known Android list content.
  • Expected result: The target product becomes visible and can be selected without relying on fixed screen coordinates.

B. Testcase: Dynamically selecting Product by scanning list based on text

Dynamic selection finds a product by its displayed name and clicks the corresponding action within the same row.

  • Scanning logic: Read currently visible product names, compare each with the requested name, and use the matching index to select its button.
  • Row relationship: Product names and “Add to Cart” controls must be taken from the same container or aligned collections.
JAVA
String wanted = "Air Jordan 4 Retro";
List<WebElement> names = driver.findElements(
    AppiumBy.id("com.shop:id/productName"));
List<WebElement> addButtons = driver.findElements(
    AppiumBy.id("com.shop:id/productAddCart"));

for (int i = 0; i < names.size(); i++) {
    if (names.get(i).getText().equals(wanted)) {
        addButtons.get(i).click();
        break;
    }
}
  • Safer row locator: Locate the product row containing the target text, then find its button relative to that row; this avoids index mismatch.
  • Failure handling: Track whether a match was found and fail with the missing product name after the maximum scroll count is reached.
  • Verification: Confirm that the button state changes or that the cart count increases after selection.

VII. Maintainability — Reusable Automation Design

A. Code optimization with user defined functions

User-defined functions reduce repeated locator and interaction code while preserving clear test intent.

  • Reusable actions: Encapsulate operations such as entering customer details, scrolling to a product, adding an item, and parsing currency.
  • Parameterized behavior: Pass changing values such as customer name, country, and product name as arguments.
JAVA
void addProduct(String productName) {
    WebElement row = driver.findElement(AppiumBy.xpath(
        "//*[@text=" + xpathLiteral(productName) + "]/.."));
    row.findElement(AppiumBy.id("com.shop:id/productAddCart")).click();
}

BigDecimal parseAmount(String value) {
    return new BigDecimal(value.replaceAll("[^0-9.]", ""));
}
  • Wait helper: Centralize explicit waiting so all actions use consistent timeout and visibility rules.
  • Page objects: Store locators and page-level operations in classes such as FormPage, ProductsPage, and CartPage.
  • Assertion boundary: Page functions should usually return state or elements; test methods should express business assertions.
  • Optimization criterion: Extract a function when behavior is repeated or conceptually meaningful, not merely to shorten a single statement.
  • Result: A test can read as a workflow: fill the form, add named products, open the cart, and validate the total.