Android/iOS Testing Perfected: 20 Appium Tricks You Need

Android/iOS Testing Perfected: 20 Appium Tricks You Need

posted 5 min read

Appium is one of the(maybe number one) most popular open-source automation tool for testing mobile applications across iOS and Android platforms. Strong libraries, wide community and documentation support and years of experience across all the QA Enginners and most importantly Selenium-like syntax makes it top choice for Native Mobile App testing. If we know that, we should know how to make it perfect too.

Appium Best Practices & Tips

1. Use Appium Inspector

Appium Inspector helps in identifying element locators efficiently. It allows testers to inspect UI elements and retrieve attributes like resource-id, accessibility-id, text, and class.

Example:

  1. Open Appium Inspector and connect to your running session.
  2. Click on elements to fetch their properties.
  3. Copy unique locators to use in your automation script, ensuring better test stability.

2. Find Exact App Names from Play Store

To correctly launch an app using Appium, you need the exact package name and main activity.

Example:

  1. Install the "Package Name Viewer" on an android test device.

  2. Use these details in your capabilities while setting up Appium.

3. Download trusted APKs

Some APK needs to be downloaded from external instead of play store. You should ALWAYS double check what you downloaded on your VD. It may not be seem harmful, but your work environment can contain sensitive information as usual.

Example:

adb install "C:\Users\YourUserName\Downloads\may-be-malware.apk"

If you dont trust, open new virtual device and do not login your google account or elsewhere, then test the app there.

4. Advanced ADB Command for Extracting Current Activity

Instead of manually searching the activity name from dumpsys window, use the following command to extract it precisely:

Example:

adb shell dumpsys window | grep -oP '(?<=mCurrentFocus=Window{)[^}]+'

This command extracts only the currently focused window, making it easier to grab the package and activity for use in Appium tests.

5. Disable Animations via ADB

Animations can slow down tests and cause flakiness. Disable them using ADB commands.

Example:

adb shell settings put global window_animation_scale 0
adb shell settings put global transition_animation_scale 0
adb shell settings put global animator_duration_scale 0

This speeds up UI interactions during automation.

6. Page Object Model (POM) Configurations

Using POM makes test scripts more structured and maintainable by separating UI elements and test logic.

But you cannot use constructor as you used in Selenium before. AppiumFieldDecorator is MUST due to its own lazy load handle nature. Its also good practice and sometimes we should go with @AndroidFindBy annotation(iOS has also its own @iOSFindBy annotation) instead of Seleniums @FindBy annotation. Because it has just 8 locators and uiAutomator and accessibility not one of them.

Example:

public abstract class LandingPage {

    public LandingPage() {
        PageFactory.initElements(new AppiumFieldDecorator(getDriver()), this);
    }

    @AndroidFindBy(accessibility = "Login Screen")
    public WebElement loginScreen;

    @AndroidFindBy(accessibility = "Echo Box")
    public WebElement echoBoxScreen;

TL&DR; following this structure makes test cases more readable and reusable.

7. Prefer Accessibility IDs and Resource IDs

Accessibility ID and Resource ID are the most reliable locators compared to XPaths, making tests more stable and faster.

Example:

driver.findElement(MobileBy.AccessibilityId("SubmitButton")).click();

This avoids issues caused by UI structure changes.

8. Handle Flakiness with Retries

Tests may fail due to temporary issues like slow network or animations. Implement retry logic to reduce false failures.

Example:

@Test(retryAnalyzer = RetryAnalyzer.class)
public void testLogin() {
    // Test implementation
}

This improves test reliability.

9. Explicit Waits

Avoid using Thread.sleep() as it introduces unnecessary delays. Instead, use explicit waits, which wait for an element until a specified condition is met.

Example:

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("login_button")));

This ensures that your test does not proceed until the element is visible.

10. Parallel Test Execution

Run tests on multiple devices simultaneously to speed up execution.

Example:

<suite name="ParallelTests" parallel="tests" thread-count="2">
    <test name="AndroidTest1">
        <classes>
            <class name="tests.LoginTest" />
        </classes>
    </test>
</suite>

This optimizes test execution time.

11. Use UIAutomator2

UIAutomator2 is the recommended automation engine for Android as it provides better stability and speed.

Example (Java):

capabilities.setCapability("automationName", "UIAutomator2");

This ensures compatibility with modern Android versions.

12. Network Conditioning

Simulate different network conditions like slow or no internet to test app behavior.

Example:

adb shell am broadcast -a com.android.intent.action.SET_NETWORK_CONDITIONS --es condition slow

This helps validate app performance under various network conditions.

13. Grant Permissions via ADB

Some apps require runtime permissions. Instead of manually accepting popups, grant permissions via ADB.

Example:

adb shell pm grant com.example android.permission.CAMERA

This ensures smooth test execution without interruptions.

14. Screenshots on Failure

Capture screenshots on test failures to debug issues effectively.

Example:

File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("failure_screenshot.png"));

This helps in analyzing failures visually.

15. Test Data Cleanup

Ensure a fresh app state before every test by resetting app data.

Example:

driver.resetApp();
// Or if you dont have complex use cases and dont want to handle before-after methods at hooks in your Driver class use
options.setNoReset(false);

This prevents stale data from affecting test results.

16. Cloud Testing Services

Use services like BrowserStack, Sauce Labs, or Firebase Test Lab to run tests on real devices in the cloud. It will also help you if you are unable to use Mac machine to test IOS.

Example:

capabilities.setCapability("browserstack.user", "your_username");
capabilities.setCapability("browserstack.key", "your_access_key");

Cloud testing provides access to multiple device configurations and reduces infrastructure costs.

Bonus: iOS Tips

Use xcuitest Automation Engine

For iOS automation, always use the XCUITest automation engine as it is the most stable and widely supported.

Example:

capabilities.setCapability("automationName", "XCUITest");

This ensures better compatibility with iOS devices.

Handle iOS Permissions Automatically

iOS apps require permissions for features like camera and location. You can pre-approve these using Appium capabilities.

Example:

capabilities.setCapability("autoAcceptAlerts", true);

This prevents permission popups from interrupting your tests.

Use Predicate Strings for Locators

Instead of XPaths, use Predicate Strings for better performance and stability.

Example:

driver.findElement(MobileBy.iOSNsPredicateString("label == 'Submit'"));

Predicate Strings execute faster and are more robust than XPath.

Use iosClassChain for Faster Element Finding

For better performance in iOS automation, prefer iosClassChain instead of XPath. It’s more efficient and faster for locating elements.

Example:

driver.findElement(MobileBy.iOSClassChain("**/XCUIElementTypeButton[`label == 'Submit'`]")).click();

This improves execution speed compared to XPath and is more reliable.

Predicate String vs iOSClassChain

  • Use Predicate String when you need more readable and flexible conditions (e.g., filtering by label, value, or name).
  • Use iosClassChain when dealing with deeply nested elements or hierarchical structures (e.g., finding a button inside a specific cell).

TL&DR: Predicate String for simple queries, iosClassChain for complex UI trees.

If performance is a concern, iosClassChain is generally faster than Predicate Strings, especially for deeply nested elements.


Following these best practices will significantly improve the stability, reliability, and efficiency of your Appium-based mobile test automation.

Let me know if you have other tips as well!

If you read this far, tweet to the author to show them you care. Tweet a Thanks

Please provide canonical link if this article is published elsewhere.
Nice coverage though...

Nope, i published here first

More Posts

The Ultimate Guide to Web Accessibility Testing: From Screen Readers to LighthouseCI

bugnificent - Mar 27

3 Pillars of Testing: How to be a good tester?

bugnificent - Apr 7

Security Testing for SDETs: Automate Vulnerability Scans with OWASP ZAP

bugnificent - Mar 28

How to Achieve Automated Testing Within Sprint?

Shivam Bharadwaj - Feb 6

How to use Builder design Pattern for test data generation in automation testing

Faisal khatri - Oct 14, 2024
chevron_left