Skip to main content
🎉 A11y Issue Detection Agent is now live! Detect accessibility issues like a WCAG expert with AI. Try now!
No Result Found
Get your setup working faster. Join our Discord for optimisation tips from elite testers. Join our DiscordJoin our Discord

Use executors to test screen reader interactions

Learn how to use executors to automate screen reader gestures, capture spoken output, and add accessibility assertions.

Screen Reader Automation is currently in the Beta phase and is available on Android and iOS devices under the Ultimate plan. To get access, contact BrowserStack Support. For more details on the Ultimate plan, check the pricing page.

With BrowserStack App Accessibility, you can automate screen reader accessibility testing by simulating screen reader interactions, capturing screen reader output, and validating accessibility metadata directly within your test scripts. This guide helps you get started with setting up and using Screen Reader Automation on Android and iOS.

How screen reader automation works

BrowserStack provides the browserstack_executor command, which gives you granular control over the screen reader environment within your tests. It is a custom extension that lets your test scripts send commands to control the screen reader on real BrowserStack devices.

The command can be used only with Appium. However, it is language-agnostic and can be used in any Appium-supported language to run tests on BrowserStack real devices.

This feature provides the following capabilities:

  • Programmatic control: Enable and disable the screen reader directly from your test scripts.
  • Gesture simulation: Programmatically simulate common accessibility gestures, such as moving between elements, activating an element, or scrolling.
  • Real output capture: Capture the screen reader’s actual spoken output as plain text.
  • Assertions: Use the captured spoken output to add assertions in your test scripts, so your app meets accessibility standards.

The following video provides an overview of the Screen Reader Automation executor’s capabilities:

Supported platforms and screen readers

You can automate screen reader accessibility testing on the following platforms and their corresponding screen readers:

Platform Screen Reader
Android TalkBack
iOS VoiceOver

Set up screen reader automation

To set up screen reader automation, execute interactions, and add assertions, select your platform and follow the corresponding steps.

Implement screen reader automation

Integrate the browserstack_executor command into your test scripts to enable or disable the screen reader, simulate screen reader gestures, or capture spoken output.

Enable or disable the screen reader

Use the screenReader action to enable or disable TalkBack.

  • To enable TalkBack:
    driver.execute_script("browserstack_executor: {\"action\":\"screenReader\",\"arguments\": {\"enable\" : \"true\"}}");
    
  • To disable TalkBack:
    driver.execute_script("browserstack_executor: {\"action\":\"screenReader\",\"arguments\": {\"enable\" : \"false\"}}");
    

Simulate screen reader gestures

Use the screenReaderGesture action to simulate common screen reader gestures, such as navigate, activate, or scroll.

  • To simulate a navigate next gesture:
    driver.execute_script("browserstack_executor: {\"action\":\"screenReaderGesture\",\"arguments\": {\"gesture\" : \"navigate_next\"}}");
    
  • To simulate an activate gesture:
    driver.execute_script("browserstack_executor: {\"action\":\"screenReaderGesture\",\"arguments\": {\"gesture\" : \"activate_item\"}}");
    
  • To simulate a scroll down gesture:
    driver.execute_script("browserstack_executor: {\"action\":\"screenReaderGesture\",\"arguments\": {\"gesture\" : \"scroll_down\"}}");
    

List of supported gestures

The following gestures are supported for TalkBack automation:

Gestures supported on both Android and iOS use the same argument names, so you can reuse them across platforms. Gestures supported on iOS only aren’t available on Android.

Gesture Argument
Move focus to next element "navigate_next"
Move focus to previous element "navigate_previous"
Activate focused element "activate_item"
Scroll down "scroll_down"
Scroll up "scroll_up"
Navigate back "back"
Return to home screen "home"

Capture spoken output

Use the screenReaderSpokenDescription action and specify the resource ID of an element to capture the spoken output of that element. If you don’t specify a resource ID, the command returns the spoken output for all elements captured by the screen reader.

  • To capture the spoken output of a specific UI element:
    driver.execute_script("browserstack_executor: {\"action\":\"screenReaderSpokenDescription\",\"arguments\": {\"resourceId\" : \"<your-element-resource-id>\"}}")
    

The command returns the spoken output as a string, which you can log, use for assertions, or save to a file for offline review.

If you specify a resource ID but the element does not have accessibility metadata, the command returns the spoken output for all elements captured by the screen reader. This allows you to debug issues related to missing accessibility labels or focus order.

Add accessibility assertions

With the captured screen reader data, you can add assertions to your test scripts. This lets you verify critical accessibility aspects:

  • Focusability: Verify that all relevant UI elements receive focus and are reachable by the screen reader.
  • Spoken output verification: Check that elements expose the correct accessibility metadata to screen readers, such as labels, roles, and hints, and that the actual spoken output matches your expected accessibility label or announcement.
  • Traversal order: Record the screen reader traversal sequence. Compare it to the Accessibility Tree or a visual test to confirm the focus order follows a logical reading flow.

Enable assertions

You can enable assertions in your test scripts by using the browserstack_executor command with the screenReaderSpokenDescription action to capture the spoken output of a specific UI element and verify it against your expected values.

To enable assertions:

driver.execute_script("browserstack_executor: {\"action\":\"screenReaderSpokenDescription\",\"arguments\": {\"resourceId\" : \"<your-element-resource-id>\"}}");

Example assertion

  • Spoken output verification:
    The following example captures the spoken output of an element and asserts that it matches the expected description:
    print("Getting spoken text of element\n")
      out = driver.execute_script("browserstack_executor: {\"action\":\"screenReaderSpokenDescription\",\"arguments\": {\"resourceId\" : \"<your-element-resource-id>\"}}");
      expected_description = "Master Switch, ON"
      actual_description = out['spoken_description'][0]
    
      if actual_description == expected_description
        puts "Assertion Passed: Spoken description is correct."
      else
        raise "Assertion Failed: Expected '#{expected_description}', but got '#{actual_description}'"
      end
    

Prerequisites

Add the voiceOver capability to your test session to allocate a VoiceOver-enabled device for your tests. If you do not add the capability, screen reader executors will not work in your test session.

Use the format that matches your existing setup:

Add the voiceOver capability inside bstack:options:

{
  "bstack:options": {
    "deviceName": "iPhone 16",
    "osVersion": "18",
    "voiceOver": true
  }
}

Add the browserstack.voiceOver capability as a top-level key:

{
  "browserstack.deviceName": "iPhone 16",
  "browserstack.osVersion": "18",
  "browserstack.voiceOver": true
}

Implement screen reader automation

Integrate the browserstack_executor command into your test scripts to enable or disable the screen reader, simulate screen reader gestures, or capture spoken output. You can run only one VoiceOver executor command at a time in a session. Parallel calls return an error.

Enable or disable the screen reader

Use the voiceOverToggle action to enable or disable VoiceOver. The state argument accepts on or off, and isn’t case-sensitive. VoiceOver isn’t enabled at session start, so enable it before you call any other VoiceOver executor.

  • To enable VoiceOver:
    driver.execute_script("browserstack_executor: {\"action\": \"voiceOverToggle\", \"arguments\": {\"state\": \"on\"}}");
    
  • To disable VoiceOver:
    driver.execute_script("browserstack_executor: {\"action\": \"voiceOverToggle\", \"arguments\": {\"state\": \"off\"}}");
    

The first voiceOverToggle call with state set to on can take longer than later calls.

Simulate screen reader gestures

Use the voiceOverGesture action to simulate common screen reader gestures, such as navigate, activate, or scroll. Gesture names are case-sensitive.

  • To simulate a navigate next gesture:
    driver.execute_script("browserstack_executor: {\"action\": \"voiceOverGesture\", \"arguments\": {\"gesture\": \"navigate_next\"}}");
    
  • To simulate an activate gesture:
    driver.execute_script("browserstack_executor: {\"action\": \"voiceOverGesture\", \"arguments\": {\"gesture\": \"activate_item\"}}");
    
  • To simulate a scroll down gesture:
    driver.execute_script("browserstack_executor: {\"action\": \"voiceOverGesture\", \"arguments\": {\"gesture\": \"scroll_down\"}}");
    

Verification

  • If successful, the command returns the gesture that was performed:
    { "success": true, "gesture": "navigate_next" }
    

List of supported gestures

The following gestures are supported for VoiceOver automation:

Gestures supported on both Android and iOS use the same argument names, so you can reuse them across platforms. Gestures supported on iOS only aren’t available on Android.

Gesture Argument Platform support
Move focus to next element "navigate_next" Android and iOS
Move focus to previous element "navigate_previous" Android and iOS
Activate focused element "activate_item" Android and iOS
Scroll down "scroll_down" Android and iOS
Scroll up "scroll_up" Android and iOS
Navigate back or dismiss "back" Android and iOS
Move focus to first element on screen "home" Android and iOS
Move focus to first element on screen "navigate_first" iOS
Move focus to last element on screen "navigate_last" iOS
Read continuously from the top of the screen "read_from_top" iOS
Read continuously from the current position "read_from_current" iOS
Move to the next item for the current rotor setting "rotor_next" iOS
Move to the previous item for the current rotor setting "rotor_previous" iOS
Pause or resume speech "pause_speech" iOS

On iOS, the following gestures behave as described:

  • The home and navigate_first gestures perform the same action of moving the screen reader focus to the first element on the screen.
  • The read_from_top and read_from_current gestures start continuous reading. Use pause_speech to pause or resume it.

Capture spoken output

Use the getVoiceOverElement action to capture the element VoiceOver is focused on and its spoken output. This action takes no arguments.

  • To capture the focused element and its spoken output:
    result = driver.execute_script("browserstack_executor: {\"action\": \"getVoiceOverElement\", \"arguments\": {}}");
    

Verification

  • The command returns the focused element’s accessibility attributes and the most recent VoiceOver announcement as plain text:
    {
    "element": {
      "elementClass": "UIButton",
      "label": "Send",
      "value": "",
      "hint": "Double tap to send message",
      "identifier": "send_button",
      "traits": 8589934593,
      "frame": { "x": 300, "y": 700, "width": 60, "height": 44 }
    },
    "spokenDescription": "Send. Button. Double tap to send message."
    }
    

The response has the following fields:

Field Description
element.elementClass Native class of the focused element, for example, UIButton.
element.label The element’s accessibilityLabel.
element.value The element’s accessibilityValue.
element.hint The element’s accessibilityHint.
element.identifier The element’s accessibilityIdentifier.
element.traits Raw UIAccessibilityTraits bitmask, as a number.
element.frame On-screen position and size, in points.
spokenDescription The most recent VoiceOver announcement, as plain text.

Considerations

  • The two parts of the response, element and spokenDescription, are independent. If element details can’t be captured, element is an empty object. If the spoken output can’t be captured, spokenDescription is an empty string. The command doesn’t fail on a partial capture, so assert only on the fields you need.
  • Unlike Android’s screenReaderSpokenDescription, this action doesn’t take a resource ID. It always reads the currently focused element.

Add accessibility assertions

With the captured screen reader data, you can add assertions to your test scripts. This lets you verify critical accessibility aspects:

  • Focusability: Verify that all relevant UI elements receive focus and are reachable by the screen reader.
  • Spoken output verification: Check that elements expose the correct accessibility metadata to screen readers, such as labels, roles, and hints, and that the actual spoken output matches your expected accessibility label or announcement.
  • Traversal order: Record the screen reader traversal sequence. Compare it to the Accessibility Tree or a visual test to confirm the focus order follows a logical reading flow.

Enable assertions

You can enable assertions in your test scripts by using the browserstack_executor command with the getVoiceOverElement action to capture the spoken output of the focused element and verify it against your expected values.

To enable assertions:

result = driver.execute_script("browserstack_executor: {\"action\": \"getVoiceOverElement\", \"arguments\": {}}");

Example assertion

  • Spoken output verification:
    The following example captures the spoken output of an element and asserts that it matches the expected description:
    driver.execute_script('browserstack_executor: {"action": "voiceOverGesture", "arguments": {"gesture": "navigate_next"}}')
    result = driver.execute_script('browserstack_executor: {"action": "getVoiceOverElement", "arguments": {}}')
    expected = "Send. Button. Double tap to send message."
    actual = result["spokenDescription"]
    assert actual == expected, f"Assertion Failed: expected '{expected}', but got '{actual}'"
    print("Assertion Passed: spoken description is correct.")
    

Error reference

The VoiceOver executor commands on iOS return the following errors. Each response includes an error code and a descriptive message.

Error code When it occurs
BROWSERSTACK_INVALID_VALUE The voiceOverToggle action is called with a state other than on or off.
BROWSERSTACK_INVALID_VOICEOVER_GESTURE The voiceOverGesture action is called with a gesture that isn’t in the supported list. Gesture names are case-sensitive.
BROWSERSTACK_INCOMPATIBLE_COMMAND_PASSED A VoiceOver executor is called on a non-iOS device. VoiceOver executors are supported on iOS only.
BROWSERSTACK_UNSUPPORTED_PRODUCT A VoiceOver executor is called outside an iOS App Automate session.
BROWSERSTACK_MULTIPLE_VOICEOVER_COMMANDS_ERROR A VoiceOver executor is called while another VoiceOver command is still running. Run commands one at a time.
BROWSERSTACK_FEATURE_NOT_AVAILABLE_IN_CURRENT_PLAN The account isn’t on the Ultimate plan.
BROWSERSTACK_VOICEOVER_NOT_AVAILABLE The session didn’t start on a VoiceOver-enabled device. Add the voiceOver capability and run the test again.
BROWSERSTACK_VOICEOVER_EXECUTOR_DISABLED VoiceOver automation is temporarily disabled for the region or device.
BROWSERSTACK_VOICEOVER_EXECUTOR_ERROR The command couldn’t run because of an internal issue. Contact BrowserStack Support if it continues.

We're sorry to hear that. Please share your feedback so we can do better

Contact our Support team for immediate help while we work on improving our docs.

We're continuously improving our docs. We'd love to know what you liked





Thank you for your valuable feedback

Is this page helping you?

Yes
No

We're sorry to hear that. Please share your feedback so we can do better

Contact our Support team for immediate help while we work on improving our docs.

We're continuously improving our docs. We'd love to know what you liked





Thank you for your valuable feedback!

Talk to an Expert
Download Copy Check Circle