TL;DR Use snapshot()
method of XCUIElement
in order to get consistent element information.
Asynchronous nature of UI Tests
Tests happen in a separate process, Test Runner, that doesn’t have access to actual views of our App. Runner talks to App using some special communication channel, probably inter-process mechanism. Our code dispatches requests to this mechanism, and then the mechanism talks to App on behalf of our code. This makes our tests asynchronous in 2 ways. First, the actual execution of a request will happen some time after our code is executed, and we don’t know when. Second, App’s state and memory changes are not blocked by our test’s code. When we do anything related to accessibility elements, e.g. print debug description or tap on element, we don’t know when it will actually happen and at what state elements will be accessed.
Implicit dynamic nature of XCUIElement
Consider this piece of code:
let cell = app.cells.matching(identifier: "mainScreenSimilarCell").element
print(cell.frame)
print(cell.identifier)
It stores an element into variable cell
, and then prints 2 fields of it. What I’ve had expected, is that frame
and identifier
would be read from a single representation of an element. But let’s take a look at test output

Notice “Find the Cell” output twice. Even though we already store element in our variable, it would still re-find element each time we access a property of it. Because of that, what we see about properties may and will be out of sync. It may even find a different element!
Of course, there are some fields of XCUIElement that read directly from Runner’s memory, without dispatching inter-process requests. But as far as I tested, all of test related properties and fields do the cycle, see “Find” and “Checkin” outputs below:

Example issue: difficult debugging
For different use cases like debugging some strange “cell accessibility identifier reuse” problem, we may want to print multiple different fields of XCUIElement
at once, just to see what happens. For that we may use debugDescription
, but the problem with it is that it’s just a huge string and extracting something specific from it would be a pain. And also, it’s event more asynchronous! I mean it’s slow, because it needs to snapshot whole app hierarchy, event if you just care about single small element. If your problem is hard to catch, debugDescription
will probably be too slow and will miss it.
Solution
Use XCUIElements snapshot().
let snapshot = try cell.snapshot()
print(snapshot.frame)
print(snapshot.identifier)

Single find, 2 print outputs, just what we want. Snapshot captures all the XCUIElementAttributes
fields and gives us representation that doesn’t change when we access it multiple times. It’s a quick and as easy to use as XCUIElement.
What led me to this investigation
Sometimes, when interacting with element (cell) queried by concrete identifier, the UI Test or accessibility system would find different, wrong element, with different identifier.
> t = 9.13s Find the "mainScreenSimilarCell" Cell
> Cell, {{211.0, 615.0}, {186.0, 189.0}}, identifier: 'mainScreenScreenshotsCell'