Driver-based Appium architecture for testing on Android

For testing on Android devices, Perfecto supports the driver-based Appium architecture introduced in Appium 1.10. This architecture is fully aligned with local Appium testing. This change applies to native, web, and hybrid app testing.

Benefits

The driver-based Appium architecture comes with the following benefits:

  • Full compatibility with Appium standard

  • Bug fixes and enhancements

  • Support of Android deep links

    Deep links are URLs that take users directly to specific content in your app. For example:

    getDriver().get("theapp://login/darlene/testing123");

    When a clicked link or programmatic request invokes a web URI intent, the Android system tries each of the following actions, in sequential order, until the request succeeds:

    1. Open the user's preferred app that can handle the URI, if one is designated.

    2. Open the only available app that can handle the URI.

    3. Allow the user to select an app from a dialog.

  • Unique Perfecto features, such as sensor injection, to complement the Appium feature set

Supported Android devices

The driver-based architecture works with any Android device that supports the UIAutomator2 (v1.25.0) automation framework.

Prerequisites

The driver-based architecture requires the following:

  • XPATH 1.0. Regular expression matching with the matches() function is not supported.

  • Appium client 6.1.0 or later.

Enable the driver-based Appium architecture

During the transition phase from pre-driver-based Appium architecture (prior to Appium 1.10) to driver-based architecture, you need to select the driver-based architecture explicitly on a per-script basis using the following designated capabilities. These capabilities control the architecture used for either native only, native and web, native and hybrid, or native, web, and hybrid.

If the new architecture is already the default, you can omit these capabilities. 

Copy

New capability for native

capabilities.setCapability("enableAppiumBehavior", true);
Copy
New capabilities for web
capabilities.setCapability("enableAppiumBehavior", true);
capabilities.setCapability("useAppiumForWeb", true);
capabilities.setCapability("browserName", "Chrome");
Copy

New capabilities for hybrid

capabilities.setCapability("enableAppiumBehavior", true);
capabilities.setCapability("useAppiumForHybrid", true);

Quantum capabilities

When working with a Quantum project, use the following capabilities.

Copy

Quantum | New capability for native

<parameter name="perfecto.capabilities.enableAppiumBehavior" value="true" />
Copy

Quantum | New capabilities for web

<parameter name="perfecto.capabilities.enableAppiumBehavior" value="true" />
<parameter name="perfecto.capabilities.useAppiumForWeb" value="true" />
<parameter name="perfecto.capabilities.browserName" value="Chrome" />
Copy
Quantum | New capabilities for hybrid
<parameter name="perfecto.capabilities.enableAppiumBehavior" value="true"></parameter>
<parameter name="perfecto.capabilities.useAppiumForHybrid" value="true" />

Alternatively, use the following syntax.

Copy
Quantum | Alternative syntax
<parameter name="perfecto.additional.capabilities" value="{'enableAppiumBehavior':true, 'useAppiumForWeb':true, 'useAppiumForHybrid':true}" />

Migrate existing Perfecto hybrid scripts to the driver-based architecture

  1. If your app uses WebViews, when creating the WebView object, set the setWebContentsDebuggingEnabled property to true. To learn more, see Android remote debugging.

  2. Change the value of the automationNamecapability from PerfectoMobile to its default value, Appium. Alternatively, because Appium is the default value, you can remove this capability.

  3. Cancel the instrumentation (there is no need to instrument the tested app). Then fix object locators, if needed, because the tree seen by the script is slightly different.

  4. Add the following capabilities with a value of true (as described above):

    • useAppiumForHybrid

    • enableAppiumBehavior

  5. Review and adjust the switch-to-WebView logic in your code: The driver can now return the list with several WebView contexts, and the best practice is switching to the last context in this list (provided that the tested WebView is currently in the front).

Work with multipe WebViews in Android hybrid apps

Sometimes, Android hybrid apps have more than one WebView (for example, one for app content and one for ads). By default, Appium might only show one WebView context—often not the one you want.

To work with multiple WebViews:

  1. Navigate to the screen with multiple WebViews and wait for them to load.

    Copy
    WebDriverWait wait = new WebDriverWait(driver, 10);
    wait.until(ExpectedConditions.presenceOfElementLocated(hybridScreen)).click();
    wait.until(ExpectedConditions.presenceOfElementLocated(webview));
  2. Define a helper method to find and switch from the NATIVE_APP context to the WebView context.

    Copy
    private String getWebContext(AppiumDriver driver) {
        for (String context : driver.getContextHandles()) {
            if (!context.equals("NATIVE_APP")) return context;
        }
        return null;
    }
  3. Call the helper method to get the WebView context and then switch to it.

    Copy
    driver.context(getWebContext(driver));
  4. Use the getWindowHandles() metho to access mutiple WebViews.

    Even within one WebView context, Appium sees multiple WebViews as separate windows via Chromedriver.

    Copy
    for (String handle : driver.getWindowHandles()) {
        driver.switchTo().window(handle);
        String content = driver.findElement(By.tagName("body")).getText();
        System.out.println(content);
    }
  5. Validate each WebView's content, such as body text, title, or URL, to confirm you are in the correct one.

Following is a complete code sample.

Copy
// 1. Wait for WebViews to Load
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.presenceOfElementLocated(hybridScreen)).click();
wait.until(ExpectedConditions.presenceOfElementLocated(webview));

// 2. Switch to the WebView Context
private String getWebContext(AppiumDriver driver) {
    for (String context : driver.getContextHandles()) {
        if (!context.equals("NATIVE_APP")) return context;  // Return the first non-native context (WebView)
    }
    return null;
}
driver.context(getWebContext(driver));  // Switch to WebView

// 3. Use getWindowHandles() to Access Multiple WebViews
// After switching to WebView context, switch between multiple WebViews
for (String handle : driver.getWindowHandles()) {
    driver.switchTo().window(handle);  // Switch between different WebViews
    String content = driver.findElement(By.tagName("body")).getText();  // Extract content from the body tag
    System.out.println(content);  // Print content for validation or interaction
}

// 4. Validate Content
// Here, you can perform checks on the WebView’s content
// For example, check if the title matches
String pageTitle = driver.getTitle();
System.out.println("WebView Title: " + pageTitle);