skip to content

In an Appium `-ios class chain`, what do the `/` and `**/` steps mean?

level: juniorimportance: must knowfreq 58%

answer

  1. two separators, one descending path
  2. steps name element types only
  3. double star crosses generations
  4. single slash means immediate child

basics

~10 s

In Appium's iOS class chain strategy, a single slash requires the next element type to be a direct child of the previous match, while a double-star slash lets it sit at any depth below.

solid answer

~40 s

`-ios class chain` is a locator strategy the Appium **XCUITest driver** declares for Apple platforms; the Android drivers, UiAutomator2 and Espresso, declare their own lists and accept nothing like it. A path is a sequence of steps, each naming an `XCUIElementType`, joined by separators. `/` means the next step must match a **direct child** of the previous match; `**/` means it may match a **descendant at any depth**. Most real paths open with `**/` — `**/XCUIElementTypeCell` — because an absolute chain from the application element down to a bell-ringing tower roster row is long and breaks whenever a developer wraps a control in another view. A path that opens with a bare type name is anchored on the application element itself.

go deeper

for a junior

Be ready to read a class chain out loud and say which step is a direct child and which may sit at any depth, and to name it as an Apple-platform strategy the Android drivers do not have.

for a middle

Explain why an opening double-star step survives a layout change that a long single-slash chain does not, and what a step can name at all: an element type, never an attribute value.

for a senior

Show judgment about how much hierarchy a path should encode on a real iOS screen, and be able to say what a find does when a path is ambiguous rather than assuming it errors.

for a principal

Own the position: an iOS-only path language buys precision that the app's own identifiers should mostly make unnecessary, and every path in a suite is hierarchy knowledge you have agreed to maintain.

## What the `-ios class chain` strategy is The Appium **XCUITest driver** declares `-ios class chain` as one of its native locator strategies for Apple platforms, alongside `xpath`, `id`, `name`, `class name`, `accessibility id`, `css selector` and `-ios predicate string`. It exists only on that side of the fence: the Android drivers, UiAutomator2 and Espresso, publish their own strategy lists and neither accepts a class chain, so a path written for an iPhone never travels to an Android session. The strategy is deliberately positioned between the two other iOS-native options. A predicate string filters an element by the element's own attributes but cannot say anything about where it sits. XPath can describe any position but is a general-purpose tree language. A class chain is a **short path over element types** that WebDriverAgent walks on the device using XCTest's own element queries, so it can express hierarchy without behaving like an arbitrary tree query. ## The two separators A class chain is a sequence of steps. Every step names an `XCUIElementType` — `XCUIElementTypeTable`, `XCUIElementTypeCell`, `XCUIElementTypeButton`, `XCUIElementTypeStaticText`, or `XCUIElementTypeAny` where the concrete type does not matter. What sits *between* two steps is the whole of this question: - `/` means **direct child**: the next step must match an immediate child of whatever the previous step matched. - `**/` means **descendant at any depth**: the next step may match a child, a grandchild, or something buried ten levels down. - A path that opens with `**/` searches from anywhere below the root; a path that opens with a bare type name is anchored on the iOS application element itself. - Neither separator walks sideways or upwards. A class chain only ever descends. | you write | what it means on iOS | typical use | |---|---|---| | `**/XCUIElementTypeCell` | any cell, at any depth | the usual opening step | | `XCUIElementTypeWindow/XCUIElementTypeTable` | a table that is an immediate child of a window | pinning a known top-level layout | | `**/XCUIElementTypeTable/XCUIElementTypeCell` | cells that are immediate children of a table | keeping a row search inside one table | ## Reading a path on the bell-ringing tower roster Take the roster screen of a bell-ringing tower roster app: one table, one cell per ringer, and inside each cell a static text with the ringer's name plus a **Ring** button. 1. `**/XCUIElementTypeTable` finds the roster table wherever the layout put it, without the test having to know how many containers wrap it. 2. `**/XCUIElementTypeTable/XCUIElementTypeCell` finds the roster rows and, because the second step uses `/`, will not accidentally reach cells belonging to a table nested inside a row. 3. `**/XCUIElementTypeCell/XCUIElementTypeButton` finds buttons that are immediate children of a row. If the app wraps its buttons in a container view, this path stops matching and a `**/XCUIElementTypeButton` search — or an extra step naming the wrapper — is needed instead. That third case is the practical difference between the separators. `/` is a promise about the app's view hierarchy; `**/` asks only about ancestry. A `/` path is the more precise of the two and the more likely to break when a developer introduces a container that changes nothing visible on screen. ## What else a step may carry Separators are only part of the grammar. Each step can be narrowed further before the next separator: - a **backtick segment** filters the step by the element's own attributes, as in ``XCUIElementTypeButton[`label == 'Ring'`]``; - a **`$...$` segment** matches the step by what it contains, which is how a class chain addresses a container by its content; - an **index** in square brackets picks one element out of that step's matches, numbered from 1, with negative numbers counting from the end. The operator vocabulary usable inside those segments is the `-ios predicate string` strategy's subject, and what a query costs to evaluate belongs with the XPath cost model. The steps, the separators and the indexes are what a class chain adds. ## Where paths go wrong - Writing a long `/` chain that mirrors today's iOS layout; every wrapper a developer adds invalidates it. - Using `**/` for every step and then being surprised that a find returns an element belonging to a different table on screen. - Putting something that is not an `XCUIElementType` in a step; attribute matching happens in the bracket segments, never in the step name. - Expecting XPath conveniences that a class chain does not have: no parent step, no sibling step, no text function. - Assuming the same string can be handed to an Android session — the Android drivers do not declare the strategy at all.

  • How would you anchor an iOS class chain when two roster tables are on screen at once?
    Give the path a distinguishing first step instead of opening on the cells. Match the table you want — by a backtick segment on its own attributes, or by stepping down from the window that holds it — and then use `/XCUIElementTypeCell` so the row search cannot leave that table.
  • What happens when a class chain path matches several elements on iOS?
    Nothing fails. A single-element find returns the first match in hierarchy order and a plural find returns them all, which is why an ambiguous path can quietly act on the wrong roster row. Narrow the step with a bracket segment or an index when exactly one element is meant.

A class chain reads like a file path: a single slash is exactly one level down, and the double star is the wildcard that skips however many levels lie in between.

saying these in an interview costs you the question

  • Claims the class chain strategy also works on Android drivers
  • Treats the single-slash and double-star separators as interchangeable
  • Thinks a step names an attribute value rather than an element type
  • Says a class chain supports parent or following-sibling axes
  • Assumes an absolute path from the application element is the stable choice