iOS accessibility identifiers provide a stable automation contract between an iOS application’s UI and XCUITest. Instead of locating elements through changing text, screen position, or fragile hierarchy paths, SDETs can use explicit identifiers to build deterministic, maintainable, and scalable UI automation.
What are iOS Accessibility Identifiers?
An accessibility identifier is a string assigned to a UI element through Apple’s accessibilityIdentifier property. Apple documents this property as a way to uniquely identify UI elements in UI automation scripts without incorrectly using the element’s accessibility label. (Apple Developer)
For example:
loginButton.accessibilityIdentifier = "loginButton"
The XCUITest can then locate it directly:
let loginButton = app.buttons["loginButton"]
loginButton.tap()
The important distinction is:
Accessibility Identifier
↓
Stable Element Identity
↓
XCUIElement Query
↓
XCUIElement
↓
Interaction
↓
Assertion
This makes the identifier more than a testing convenience. It becomes part of the application’s automation interface.
Definition
iOS accessibility identifiers are developer-defined strings assigned to iOS UI elements so automation frameworks such as XCUITest can locate those elements using a stable identifier. Apple’s UIAccessibilityIdentification protocol exposes accessibilityIdentifier for this purpose. (Apple Developer)
They are especially valuable when the visible UI changes but the logical purpose of the element remains the same.
For example, a button may display:
Log In
today and:
Sign In
after a product change.
Its automation identity can remain:
loginButton
The test therefore does not need to change simply because the visible wording changed.
Key Points
- Use identifiers for important interactive elements.
- Keep identifiers stable across UI redesigns.
- Prefer semantic names over visual descriptions.
- Do not use visible text as the primary automation contract.
- Avoid positional selectors when a stable identifier exists.
- Keep identifiers unique within the relevant UI hierarchy.
- Treat identifiers as part of the application-test contract.
- Use the same naming convention across the application.
- Separate accessibility labels from automation identifiers.
- Validate identifiers during UI test development.
Apple specifically notes that an identifier can uniquely identify an element in UI automation and helps avoid using the accessibility label for that purpose. (Apple Developer)
Why Reliable Identifiers Matter in XCUITest
Consider this test:
app.buttons["Log In"].tap()
It looks simple, but it couples the test to visible text.
Now consider:
app.buttons["loginButton"].tap()
The second version couples the test to the semantic purpose of the element.
That difference becomes important when applications support:
- Multiple languages
- Dynamic content
- A/B testing
- Frequent UI redesigns
- Different device sizes
- Dark and light themes
- Accessibility settings
- Product terminology changes
The UI can change while the automation contract remains stable.
Identifier vs Accessibility Label
These concepts should not be confused.
Accessibility Identifier
Used primarily as a stable programmatic identity.
button.accessibilityIdentifier = "checkoutButton"
Accessibility Label
Describes the element to assistive technologies and users.
button.accessibilityLabel = "Checkout"
The automation test can use:
app.buttons["checkoutButton"]
while VoiceOver-oriented accessibility behavior can use an appropriate human-readable label.
Apple explicitly recommends identifiers for UI automation rather than inappropriately setting or accessing an element’s accessibility label. (Apple Developer)
This gives us a useful architecture:
UI Element
│
├── accessibilityIdentifier
│ └── Automation identity
│
└── accessibilityLabel
└── Human/assistive description
UIKit Implementation
For UIKit applications, identifiers can be assigned directly to supported UI objects.
Example:
final class LoginViewController: UIViewController {
@IBOutlet weak var emailTextField: UITextField!
@IBOutlet weak var passwordTextField: UITextField!
@IBOutlet weak var loginButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
emailTextField.accessibilityIdentifier = "login.emailField"
passwordTextField.accessibilityIdentifier = "login.passwordField"
loginButton.accessibilityIdentifier = "login.submitButton"
}
}
The corresponding test becomes:
let app = XCUIApplication()
let emailField = app.textFields["login.emailField"]
let passwordField = app.secureTextFields["login.passwordField"]
let loginButton = app.buttons["login.submitButton"]
emailField.tap()
emailField.typeText("qa@example.com")
passwordField.tap()
passwordField.typeText("Password123!")
loginButton.tap()
This creates a clean mapping between application code and test code.
SwiftUI Implementation
SwiftUI provides a convenient modifier for assigning an accessibility identifier:
👉 Continue reading the full article on skakarh.com →
Originally published at skakarh.com/ios-accessibility-identifiers.
Subscribe to QA Pulse by SK —
weekly signal for QA, Test Automation and AI in Software Engineering.
Top comments (0)