skip to content

In Appium on Android, why does an `accessibility id` locator miss a button whose visible label reads Scan pass?

level: middleimportance: should knowfreq 38%

answer

  1. description and caption are different fields
  2. Android compares one field only
  3. no fallback exists on that platform
  4. the other platform hides the same omission

basics

~20 s

Because on Android the strategy compares only content-desc, a field separate from the text a widget renders. A button can display a caption and carry no description, and there is no fallback, so the find fails.

solid answer

~40 s

On Android, UiAutomator2 resolves `accessibility id` against the element's `content-desc` and nothing else. The caption a widget paints on screen lives in a different field, so a stadium turnstile button that reads *Scan pass* while carrying no description is not addressable by this strategy at all — and because Android has no fallback, the find fails outright rather than matching the caption. The same mistake behaves differently on Apple platforms: there the strategy goes through `name`, which falls back to the element's visible `label` when the identifier is empty, so the identical omission can produce a passing find against the caption. One missing app-side field, a red result on Android and a green one on Apple platforms.

go deeper

for a junior

Remember that on Android the description and the on-screen text are different fields, and that accessibility id reads only the description. That single distinction explains most first-week failures with this strategy.

for a middle

Explain why Android fails outright while Apple platforms can match the caption instead, and be able to name the field each one reads. The contrast, not the Android half alone, is the answer being looked for.

for a senior

Show how you tell this apart from a timing failure in a real run, and argue why repairing it in the build beats swapping the failing platform onto another strategy and shipping two addresses for one control.

for a principal

Own the policy question underneath: whether controls must carry a dedicated address on both platforms before a case may depend on them, and how a team notices when only one of the two builds honours that.

## The description and the caption are two different fields On Android the `accessibility id` strategy is resolved by the UiAutomator2 driver against the element's **`content-desc`** — the accessibility description, whose app-side source is `contentDescription`. The text a widget draws on screen is a separate property of that widget. They often say similar things, and they are frequently confused for one another, but the driver never conflates them: your search string is compared with the description, full stop. So on a stadium turnstile entry screen, a primary button rendering *Scan pass* may have: - a description equal to the caption, in which case searching for `Scan pass` matches; - a description that is a deliberate token such as `turnstile-scan-gate`, in which case only that token matches; - no description at all, in which case **nothing** matches it through this strategy. The third case is the one that produces the question. The element is on screen, plainly visible, obviously tappable — and completely unaddressable by `accessibility id`. ## Why it fails rather than falling back Android's behaviour here is blunt and, in the end, helpful: there is no second rule. An empty `content-desc` is not quietly replaced by the caption, by the widget class, or by anything else. The find simply does not match, and the failure surfaces at the moment the locator is wrong rather than several releases later. That bluntness is worth valuing, because the alternative is what Apple platforms do. ## The same omission on Apple platforms On Apple platforms the XCUITest driver resolves the strategy through the element's `name` attribute, and `name` is the element's `identifier` **or**, when that is empty, its `label` — the visible caption. So the identical app-side omission produces the opposite symptom. | The developer set no dedicated field | Android (UiAutomator2) | Apple platforms (XCUITest) | |---|---|---| | Attribute the strategy reads | `content-desc` | `name` | | Result of the lookup | no match, the find fails | may match the visible caption | | How it surfaces | a red step, immediately | a green step, until copy or locale changes | | What it proves about the build | that the field is missing | nothing either way | A cross-platform team meets this as an apparent contradiction: *the locator works on the iPhone and not on the Android phone, so the Android build must be broken*. The more useful reading is that both builds are missing the same thing, and only one of the two platforms is willing to say so. ## Recognising it in a real run Symptoms that point at a missing description rather than at timing or hierarchy: - The element is visible in a screenshot at the moment of the failure, so the case is not a synchronisation problem dressed up as a locator problem. - The search string looks like product copy — words a user would read — rather than a token nobody would ever display. - The same string works on the Apple platform lane and only ever fails on Android. - Other elements on the same screen resolve fine, which rules out session-wide causes. ## What to do about it 1. Read the element's `content-desc` on Android. If it is blank, you have your answer and no locator rewrite will change it. 2. Do not repair it by switching the Android half to a different strategy. That produces a passing test with two unrelated addresses for one control, which is the outcome a shared address exists to avoid. 3. Decide on the token you want the control to answer to, and use a value that could never be mistaken for product copy — that choice also stops the Apple-platform fallback from matching a caption by accident. 4. Get the missing field populated in the build, on both platforms, and only then collapse the locator back to one shared constant. 5. Re-run both lanes against the new builds before trusting the shared address again. ## What an interviewer is listening for The shallow answer is that the button has no accessibility id. The answer that shows understanding says which field Android actually reads, points out that the caption lives elsewhere, and then draws the contrast unprompted: Android fails loudly on a missing description, while Apple platforms can pass on the caption instead — so a green Apple-platform run is not evidence that the Android failure is a locator bug. That contrast is exactly the kind of platform divergence a cross-platform mobile suite has to be designed around rather than discovered by accident.

  • The same locator passes on the Apple platform lane. Does that prove the Android build is at fault?
    No. On Apple platforms `name` falls back to the element's visible `label`, so the pass may have matched the caption rather than an identifier. Both builds can be missing the dedicated field, with only Android reporting it. Check the Apple element's `name` against its caption before concluding anything.
  • Would rewriting the Android locator with a different strategy be a fix?
    It makes the step pass, but it splits one control into two unrelated addresses and abandons the shared address entirely. The defect is a missing app-side field, so the repair belongs in the build; changing strategy only relocates the problem into the suite.

saying these in an interview costs you the question

  • Assumes accessibility id matches whatever text the widget renders.
  • Treats the failure as a wait or synchronisation problem.
  • Concludes the Android build is broken because the Apple lane passes.
  • Expects Android to fall back to the caption when the description is empty.
  • Fixes it by swapping strategies instead of populating the missing field.