skip to content

In Appium, where does a scroll-into-view step fail for a missing row on Android versus iOS?

level: seniorimportance: nice to knowfreq 34%

answer

  1. same defect, different failure shapes
  2. Android pays for the whole budget
  3. iOS never reaches the scroll
  4. find-time versus scroll-time failure

basics

~20 s

Android fails late: the UiAutomator2 server spends its whole search-swipe budget before the find reports nothing. iOS fails early, because mobile: scrollToElement needs an element handle, so the find fails first and the scroll never runs at all.

solid answer

~40 s

Same defect, two different failure shapes. On Android, `UiScrollable.scrollIntoView` is one request that swipes and rescans on the device, so a row that is not there costs the **whole search budget** before the find answers - a slow, late no-such-element error that looks identical to a container which never scrolled. On iOS, XCUITest's `mobile: scrollToElement` needs an element handle, so a missing row fails at the **find**, cheaply, before any scrolling is attempted. There is a third shape on iOS: the snapshot lists a laid-out but off-screen row, the find succeeds, and the scroll then fails because the element never becomes `hittable`. Reading which of the three you got is most of the triage.

go deeper

for a junior

Know that a scroll-into-view step can fail in more than one place, and that on iOS the row has to be found before it can be scrolled to at all. That ordering explains most of what you will see.

for a middle

Explain why the Android failure is slow and the iOS one is fast: the Android loop runs on the device inside one request, while the iOS command needs an element handle it never gets.

for a senior

Demonstrate triage. Say which evidence separates a missing row from a container that never scrolled, and treat an iOS find failure and an iOS scroll failure as two different defects in reporting.

for a principal

Own the cost model. Argue for a bounded search budget as a fleet-wide default and for failure messages that distinguish absence from unreachability, because ambiguous failures are what make a suite expensive to keep.

## One defect, three different failures A missing appointment row in a pet-grooming app is a single product fact. How your suite experiences it depends entirely on which driver is running, because the two scroll-into-view designs put the search in different places. Knowing the shape of each failure tells you where to look before you have read a log line. ## Android: a late failure that costs the whole budget With `-android uiautomator` and `UiScrollable.scrollIntoView`, the swipe-and-rescan loop runs on the device inside one request. When nothing matches: - The server keeps swiping until the search budget is spent or the container can go no further. - Only then does the request answer, as a **no-such-element error from the find**. - The wall-clock cost is the budget multiplied by one swipe, which is why this failure is the slow one. - The error cannot distinguish "the row is not in the app" from "the wrong container was matched" or "the list never moved". That last point is the trap. Three quite different causes converge on one message, and the only thing you know for certain is that the on-device loop gave up. ## iOS: an early failure at the find XCUITest's `mobile: scrollToElement` takes an element handle, so the order is fixed: find, then scroll. A row that does not exist has no handle, so: 1. The find fails first, usually fast, as a plain no-such-element error. 2. `mobile: scrollToElement` is never posted at all. 3. Nothing has been swiped, so the app is exactly where it started when you inspect it. The cheapness cuts both ways. It is quick, but it also collapses "not laid out yet" and "not in the app" into the same empty match set, so a fast failure is not by itself evidence that the row is absent. ## iOS again: the find succeeds and the scroll still fails WebDriverAgent's snapshot routinely lists elements that are laid out but off screen, so on iOS the find often succeeds for a row the user cannot see. Then `mobile: scrollToElement` runs and can still fail, because its contract is reachability: it scrolls the element's container until the element is `hittable`, and errors when it cannot get there. That happens when the element is not inside a scrollable container at all, or when something else sits over the place a touch would land. ## Triage table | Symptom | Platform | Most likely cause | |---|---|---| | Slow failure, list visibly scrolled to the end | Android | the row really is absent, or the budget was too small | | Slow failure, list never moved | Android | the outer selector matched the wrong container, or nothing scrollable | | Instant failure, nothing on screen changed | iOS | the find failed; the scroll was never posted | | Error after a successful find | iOS | the element cannot be made `hittable` where it sits | ## How to make each one legible The failures are shaped by the design, but their legibility is yours to fix: - Bound the Android search budget deliberately rather than leaving it at whatever the default is, so a missing row fails in a time you chose. - On Android, capture something that proves the container moved - the first visible row before and after - so "absent" and "never scrolled" stop looking alike. - On iOS, treat a find failure and a scroll failure as different defects in reporting; they point at different parts of the app. - After an iOS scroll, read the element's reachability rather than tapping straight away, so a hittability problem is reported as one. - Keep the same logical target expressed once per platform, so a failure on one platform can be reproduced on the other without rewriting the step. ## Why this is worth interview time A candidate who has only used the happy path describes both platforms as "it scrolls until it finds it". A candidate who has debugged a real fleet knows that the Android version pays for its search whether or not it succeeds, that the iOS version cannot even start without a successful find, and that an iOS find succeeding proves far less than an Android one does. Those three sentences are the whole content of this leaf.

  • On Android, how do you tell a genuinely missing row apart from a container that never scrolled?
    Prove the container moved. Read an identifying row before and after the attempt, or narrow the outer `UiSelector` to the list you mean by resource id so that a wrong-container match becomes a different, earlier failure. Without that evidence both causes arrive as the same no-such-element error.
  • Why is a fast find failure on iOS weaker evidence than a slow one on Android?
    On Android the loop has actually swiped the container, so the failure follows a real search. On iOS the find only inspects the current snapshot, and a row that has not been laid out is indistinguishable from a row the app never had. The cheap failure has done less work to earn its verdict.

saying these in an interview costs you the question

  • Assumes both platforms fail at the same step
  • Treats a slow Android failure as a network problem
  • Thinks an iOS find failure means the scroll ran and failed
  • Never bounds the Android search-swipe budget
  • Reads a successful iOS find as proof the row is reachable