Skip to content
QA Knowledge Hub

Mobile testing and Appium interview questions

Updated 2026-11-13 · 16 min read

Thirty questions on mobile app testing and Appium, from what to test on a real device to why an XPath locator is slow. Checked against the Appium 3 documentation; the Java code compiles with java-client 11.0.0 but was not run on a device.

Mobile interviews start with testing sense (what is different about a phone) and then move to Appium: how it is put together, how you find elements, and why mobile tests are slower and flakier than web tests. Service companies in India often pair Appium with Java and TestNG, so the code here is Java, with one Python example.

Mobile testing basics

1. How is testing a mobile app different from testing a website?

The app runs on thousands of device and OS combinations with different screens, memory and manufacturer changes to Android. It lives with interruptions: calls, notifications, low battery, switching between Wi-Fi and mobile data, losing the network in a lift. It is installed and updated, so upgrade paths and old versions in users' hands matter. It asks for permissions, runs in the background, and uses gestures, the camera, GPS and biometrics. And release is slower: a bug in a store build can take days to fix for every user.

2. What are native, hybrid and mobile web apps?

A native app is built with the platform's own tools (Kotlin or Java for Android, Swift for iOS) or a cross-platform framework that renders native controls. A mobile web app is a website opened in the phone's browser. A hybrid app is a native shell that shows web content inside a WebView. For testing, the type decides the tools: a hybrid app needs switching between the native and web contexts (question 20), and a mobile website can be tested with browser tools.

3. Emulators, simulators or real devices: when do you use which?

Android emulators and iOS simulators are free, fast to reset and good for most functional automation in CI. Real devices are needed for what emulators do not reproduce well: performance on low-end hardware, battery and heat, camera, fingerprint, push notifications on some setups, OEM-specific behaviour, real network conditions and installing from the store. A common split is emulators for every build and a smaller set of real devices (your own or a device cloud) for nightly runs and release checks.

4. How do you choose which devices to test on?

From data, not habit: the app's own analytics (top models, OS versions, screen sizes), then add the oldest OS version the app supports, a low-memory phone, a large screen or tablet if supported, and devices from the manufacturers your users actually have. In India that usually means testing more mid-range and budget Android phones than flagship ones. Review the list every few months as the user base changes.

5. Which mobile-specific scenarios do you always test?

Interruptions (incoming call, notification, alarm during a payment), backgrounding and returning (is the form data still there?), killing the app from recents, network changes and offline mode, permission denied and later granted, rotation, low storage, different font sizes and dark mode, deep links, and install, update and uninstall. There are ready-made lists for install, update and uninstall and push notifications.

6. How would you test a UPI payment in a mobile app?

The app hands off to a UPI app and must handle every way the user can come back: success, failure, the user pressing back, the UPI app being killed, no UPI app installed, and a timeout where the bank's final status arrives later. Check that the order status is confirmed from the server (not from the app-switch result alone), that a payment is never taken twice when the user retries, and that the pending state is shown clearly. Use the provider's sandbox and test credentials only. The detailed cases are in UPI payment test cases and OTP verification test cases.

7. Which adb commands should a tester know?

adb devices -l                                  # connected devices and emulators
adb install -r shop-debug.apk                   # install, -r keeps data when reinstalling
adb shell pm clear com.example.shop             # wipe the app's data, like a fresh install
adb logcat                                      # the device log, for crash stack traces
adb exec-out screencap -p > screen.png          # screenshot to your machine
adb shell screenrecord /sdcard/demo.mp4         # record the screen (stops at 3 minutes by default)
adb pull /sdcard/demo.mp4                       # copy the recording to your machine

logcat is the one that matters most: a crash report with the stack trace from the log is fixed much faster than "the app closed". These are from the Android adb documentation and were not run for this page; the package name is a placeholder.

Appium architecture and setup

8. What is Appium, and how is it built?

An open-source automation tool for mobile (and some desktop) apps that speaks the W3C WebDriver protocol, the same protocol Selenium uses. Your test uses a client library (Java, Python, JavaScript and others) to send commands to the Appium server. The server passes each command to a driver for the platform, such as UiAutomator2 for Android or XCUITest for iOS, which uses the platform's own automation framework to act on the device. You do not need to change or recompile the app, though a debug build with good accessibility ids helps a lot.

9. What changed from Appium 1 to Appium 2 and 3?

Appium 2 split the drivers out of the server: you install only the drivers you need with appium driver install. The default server path changed from /wd/hub to /, Appium-specific capabilities must carry the appium: prefix, and the old JSON Wire Protocol touch endpoints went away in favour of W3C Actions and driver mobile: commands. Appium 3 is a smaller upgrade: it needs Node 20.19 or newer, removes more deprecated endpoints, and requires a driver prefix on --allow-insecure features (for example uiautomator2:adb_shell).

Likely follow-up: Your old tests fail with a 404 on session creation after upgrading. What is the first thing you check? The server URL: tests written for Appium 1 often still use http://127.0.0.1:4723/wd/hub. Either remove /wd/hub or start the server with --base-path=/wd/hub.

10. How do you set up Appium for Android?

Install Node.js, the Android SDK (with ANDROID_HOME set) and a JDK; then:

npm install -g appium
appium driver install uiautomator2
appium driver doctor uiautomator2   # checks the prerequisites for this driver
appium                              # starts the server on port 4723

appium setup installs the mobile drivers in one go (UiAutomator2, Espresso, and XCUITest only on macOS). adb devices should list your emulator or phone before you start. These commands are from the official quickstart; they were not run here.

11. What are capabilities? Show a session start.

Capabilities are the key-value settings sent when a session starts: which platform, driver, device and app. platformName is a standard WebDriver capability; Appium's own carry the appium: prefix (client option classes add it for you).

UiAutomator2Options options = new UiAutomator2Options()
        .setDeviceName("Android Emulator")
        .setApp("/builds/shop-debug.apk")
        .setAutoGrantPermissions(true)
        .setNewCommandTimeout(Duration.ofSeconds(120));
AndroidDriver driver = new AndroidDriver(new URI("http://127.0.0.1:4723").toURL(), options);

The same in Python:

from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy

options = UiAutomator2Options()
options.device_name = "Android Emulator"
options.app = "/builds/shop-debug.apk"
options.auto_grant_permissions = True
options.no_reset = False
options.new_command_timeout = 120

print(options.to_capabilities())
print(AppiumBy.ACCESSIBILITY_ID, "|", AppiumBy.ID, "|", AppiumBy.ANDROID_UIAUTOMATOR, "|", AppiumBy.IOS_PREDICATE, "|", AppiumBy.IOS_CLASS_CHAIN)

Running the Python example printed {'automationName': 'UIAutomator2', 'platformName': 'Android', 'appium:deviceName': 'Android Emulator', 'appium:app': '/builds/shop-debug.apk', 'appium:autoGrantPermissions': True, 'appium:noReset': False, 'appium:newCommandTimeout': 120} and then the locator strategy names used in question 15.

12. What do noReset and fullReset do?

By default the app's data is reset before a session. appium:noReset set to true skips that: the app is not stopped and its data is not cleared, which is faster and keeps a logged-in state, but tests can leak state into each other. appium:fullReset set to true uninstalls the app before the session, which is slowest and cleanest. Many teams use the default for most tests and a clean state where it matters, such as onboarding and first-launch tests.

13. What are appPackage and appActivity, and when do you need them?

On Android, the package identifies the app (com.example.shop) and the activity is the screen to start. When you give appium:app (an APK), UiAutomator2 works them out from the APK. You set them when starting an app that is already installed, or when the app opens a different first activity than the default (then appium:appWaitActivity helps). Ask the developers for the right values; the driver documentation has a troubleshooting guide for activity start-up errors.

14. What is Appium Inspector used for?

A tool (a desktop app, or an Appium server plugin) that starts a session with your capabilities, shows a screenshot of the app next to its element tree, and lets you click an element to see its attributes (resource id, content description, text, class) and try locators. Use it to choose stable locators and to show developers which elements are missing accessibility ids. In Appium 3, attaching Inspector to an already running session needs the session_discovery feature to be allowed on the server.

Locators and interactions

15. Which locator strategies do you prefer in Appium, and why?

In order: accessibility id (content description on Android, the name on iOS), then resource id on Android; then the platform's native query (-android uiautomator, or -ios predicate string and -ios class chain); XPath last.

driver.findElement(AppiumBy.accessibilityId("email-input"));
driver.findElement(AppiumBy.id("com.example.shop:id/password"));
driver.findElement(AppiumBy.androidUIAutomator("new UiSelector().text(\"Log in\")"));

Accessibility ids are fast, survive layout changes and make the app better for screen-reader users, so asking developers to add them is a fair request. Text-based locators break when the app is translated.

16. Why is XPath slow and brittle in Appium?

To answer an XPath query, the driver first builds the whole page source as XML from the device and then searches it, which costs time on every lookup. The XCUITest driver's own documentation warns it can be up to ten times slower. Long XPaths also break whenever the layout changes. Use it only when you need relationships (the price next to a product name) that other strategies cannot express, and keep it short.

Likely follow-up: What else does the UiAutomator2 driver documentation warn about? That Google plans to remove the UiSelector classes the -android uiautomator strategy is built on, so do not build your whole locator strategy on it either.

17. How do you wait in Appium?

The same as Selenium: explicit waits for a condition, never fixed sleeps.

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(15));
wait.until(ExpectedConditions.elementToBeClickable(AppiumBy.accessibilityId("email-input")))
        .sendKeys("[email protected]");

Mobile needs longer timeouts than web for app launch and screen transitions, so set them per action rather than raising a global implicit wait, which makes every "element should be absent" check slow.

18. How do you perform a swipe? What happened to TouchAction?

The old TouchAction and MultiTouchAction classes used JSON Wire Protocol endpoints that Appium 2 removed. Use W3C Actions, which describe a pointer moving and pressing:

var size = driver.manage().window().getSize();
int x = size.width / 2;
PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
Sequence swipe = new Sequence(finger, 1)
        .addAction(finger.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), x, (int) (size.height * 0.8)))
        .addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()))
        .addAction(finger.createPointerMove(Duration.ofMillis(600), PointerInput.Origin.viewport(), x, (int) (size.height * 0.3)))
        .addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
driver.perform(List.of(swipe));

Or the driver's gesture commands, which are shorter, such as mobile: swipeGesture, mobile: scrollGesture and mobile: longClickGesture on UiAutomator2. Coordinates as fractions of the screen size, as above, work across screen sizes better than fixed pixels.

19. How do you scroll to an element that is not on screen yet?

Scroll in steps and look again, with a limit. On UiAutomator2, mobile: scrollGesture returns whether more scrolling is possible, which gives a clean stop condition:

Object canScrollMore = driver.executeScript("mobile: scrollGesture", Map.of(
        "elementId", ((RemoteWebElement) list).getId(),
        "direction", "down",
        "percent", 0.75));

Call it in a loop until the element is found or the result is false. On Android the -android uiautomator strategy can also scroll with new UiScrollable(...).scrollIntoView(...), with the deprecation caveat in question 16.

20. How do you test a hybrid app?

Switch context. The app starts in NATIVE_APP; when a WebView is on screen, the driver lists contexts such as WEBVIEW_com.example.shop, and after switching to it you use normal web locators (CSS, id) inside the web content. Switch back to NATIVE_APP for native controls. On Android the app's WebView must allow debugging (developers turn this on for test builds), and the driver needs a Chromedriver that matches the WebView version. The capability appium:autoWebview starts the session in the web context directly.

21. How do you handle permission pop-ups and system alerts?

On Android, appium:autoGrantPermissions grants the permissions the app asks for when the session starts. On iOS, appium:autoAcceptAlerts or appium:autoDismissAlerts handle alerts automatically, including privacy permission prompts. But permission behaviour is itself worth testing: write separate tests that deny a permission and check that the app explains why it needs it and still works where it can.

22. What are the common small interactions that trip people up?

The soft keyboard covering a button (hide it, or scroll), the Android back button (driver.navigate().back()), rotating the screen, putting the app in the background and bringing it back, and deep links that should open a specific screen. Each one needs a deliberate step in the test; on a real user's phone they happen all the time.

Framework and execution

23. How do you structure page objects for Android and iOS in one project?

One page object per screen with the actions the test needs (login(email, password)), and the locators chosen per platform. Java's page factory annotations @AndroidFindBy and @iOSXCUITFindBy do this in Appium's Java client; without them, keep a small locator map per platform. Platform-specific flows (a native date picker on iOS, a back button on Android) go into separate methods, not into if statements scattered through tests. The general patterns are in automation framework design.

24. How do you run Appium tests in parallel?

Each session needs its own device and its own ports. On Android, give each session a unique appium:udid (or appium:avd for emulators) and a unique appium:systemPort, plus unique chromedriverPort and mjpegServerPort if you use WebViews or screen recording. On iOS, set appium:udid always, and for parallel simulator runs the docs suggest a unique appium:derivedDataPath. One Appium server can manage several sessions; the driver documentation calls this the preferred approach. And as always, give each parallel test its own test account.

25. How do you run mobile tests in CI?

Start an emulator in the pipeline (headless, from a saved snapshot to save boot time), install the build produced earlier in the pipeline, start the Appium server, run the tests and collect evidence. Emulators need hardware acceleration, which not every CI machine provides. Many teams run a smoke set on emulators for each build and a wider run on a device cloud nightly. Keep the APK as a build artifact so a failure can be reproduced with the exact same build.

26. What evidence do you collect when a mobile test fails?

A screenshot at the moment of failure, the page source (element tree), the device log (logcat for Android), the Appium server log, a screen recording for flows with animations, and the device, OS version and app build number. Without the device details and build number, a developer usually cannot reproduce it.

Scenarios

27. A test passes on the emulator and fails on a real device. Where do you look?

Differences between them: the real device is slower (missing waits show up), the screen size changes what is visible without scrolling, the manufacturer's Android version shows extra pop-ups (battery optimisation, autostart permissions), the keyboard is different, the real network is slower, or the device has old app data. Reproduce by hand on the device, compare the page source with the emulator's, and check logcat for errors.

28. Tests became much slower after someone added a lot of XPath locators. What do you do?

Measure first: time the lookups or compare run times before and after. Replace XPaths with accessibility ids or resource ids, ask developers to add ids where none exist, and keep XPath only where a relationship is really needed. Also check for implicit waits being combined with "element absent" checks, which wait the full timeout each time.

29. Your Appium suite is flaky. What are the usual causes?

Animations and transitions (wait for the final state, or ask for a test build with animations off), fixed sleeps, tests depending on each other through noReset, shared test accounts in parallel runs, system pop-ups appearing at random, emulator instability in CI, and network calls to real services. Track which tests fail and why; fix the cause instead of adding retries. The same thinking as for web is in finding and fixing flaky tests.

30. The app crashes sometimes and you cannot reproduce it on demand. How do you report it?

Collect what you have: the logcat output with the crash stack trace (the most useful thing), the device, OS version and app build, what you were doing just before, network conditions, and how often it happened. Check the crash reporting tool the team uses for the same stack trace from other users, and compare with recent changes. Then try to narrow it down: low memory, backgrounding during a network call and rotation during loading are common triggers. A report with a stack trace and build number is worth far more than "app crashes sometimes".

Quick quiz

  1. Which capability prefix do Appium-specific capabilities need from Appium 2 onwards?
  2. Name two locator strategies to prefer over XPath on Android.
  3. A test starts the Appium session at http://127.0.0.1:4723/wd/hub and gets a 404 on Appium 3 with default settings. Why?
  4. What does appium:noReset set to true change, and what is the risk?
  5. What must be unique for each parallel Android session on one machine, besides the device itself?
Answers
  1. appium: (for example appium:automationName).
  2. Accessibility id and resource id (id). The -android uiautomator strategy is also faster than XPath.
  3. The default base path is / since Appium 2. Use http://127.0.0.1:4723 or start the server with --base-path=/wd/hub.
  4. The app's data is not cleared before the session, which is faster but lets one test's state affect the next.
  5. appium:systemPort (and chromedriverPort and mjpegServerPort if you use WebViews or recording).

Practise it

There is no mobile app in the free practice kit, so practise the testing side first: take the push notification and install and update checklists and run them by hand on an app you use every day. For automation, follow the official Appium quickstart with an Android emulator and a sample app, open it in Appium Inspector, and write one test that logs in using accessibility ids only. Then read Appium vs Espresso and XCUITest for the "why Appium" question.

Quick answers

Which Appium version does this page describe?

Appium 3 (3.9.0 was the latest on npm when this was written) with the UiAutomator2 and XCUITest drivers. Most answers also hold for Appium 2; the differences from Appium 1 are in question 9.

Do I need a Mac to automate iOS apps with Appium?

For the XCUITest driver, yes: it relies on Apple's Xcode tooling, which runs on macOS. Teams without Macs often use a cloud device provider for iOS.

Was the code on this page run on a phone?

No. The Java examples were compiled against Appium java-client 11.0.0 and Selenium 4.52.0, and the Python options example was run to print the capabilities it builds. Nothing was run against a device or emulator, so treat the code as a starting point to try on yours.

Sources

Want a project you can show in interviews?

The portfolio project kit walks you through testing a deliberately buggy app with Selenium or Playwright and API tests, then explaining it. The app itself is free.