tvOS Automation
The XCUITest driver supports automation of the tvOS platform. The driver is compatible not only with simulators, but also with real wired and wireless devices.
All tvOS sessions must set their platformName capability to tvOS (instead of iOS).
Simulator Setup¶
Apart from installing the simulator itself, no additional configuration is needed - you can start a
session right away. Make sure to provide the simulator's deviceName and platformVersion:
{
"platformName": "tvOS",
"appium:automationName": "XCUITest",
"appium:deviceName": "<apple-tv-simulator-name>",
"appium:platformVersion": "<tvos-version>",
...
}
Real Device Setup¶
Similarly to real iOS/iPadOS devices, real tvOS devices also have several additional prerequisites. For wireless devices, configuration is highly dependent on your tvOS version.
Wireless tvOS 18 or Later¶
Devices running tvOS 18 or later use Remote XPC services for pairing and communication. This
functionality is provided by the optional appium-ios-remotexpc
library. You can also skip this Remote XPC approach and use the solutions described in the tvOS 17
section, though they are limited and less reliable compared to Remote XPC.
-
Ensure you are using XCUITest driver
>= 10.30.0, and have installedappium-ios-remotexpc >= 0.13.0 -
Set up the common configuration described in the Real Device Setup document, including the provisioning profile
-
Pair your Apple TV device to the driver, similarly to how it was paired to Xcode in step 2:
- Enable discovery mode in Settings -> Remotes and Devices -> Remote App and Device
-
Run the dedicated driver script for pairing (
sudorequired):The above command will return a prompt for selecting a specific device. You can also skip interactive selection by using the
--deviceoption. See the Scripts reference page for more information. -
When prompted, enter the PIN that appears on the Apple TV
If successful, the script will print an identifier for the paired Apple TV device. This identifier may be different from the device's standard UDID - in such cases it should replace the standard UDID in all future actions.
For additional details on this procedure (discovery, cryptography, credential storage, troubleshooting), refer to the full pairing guide in the
appium-ios-remotexpcproject. -
Start a Remote XPC tunnel for your Apple TV, using another driver script (
sudorequired):It is also recommended to set the
--disconnect-retry-max-attemptsflag to3or more, as disconnects are likely to occur. Refer to the Remote XPC guide and Scripts reference page for more details. -
Launch the Appium server (in a separate process from the Remote XPC tunnel), then start a session as normal, making sure to use the UDID from step 3:
Wireless tvOS 17 or Later¶
For devices running tvOS 17, the approach slightly differs depending on your Xcode version. It also works for devices running tvOS 18 or later, but is discouraged in favor of the aforementioned Remote XPC approach.
-
Ensure you are using XCUITest driver
>= 10.10.0 -
Set up the common configuration described in the Real Device Setup document, including the provisioning profile
-
Launch the Appium server with the
APPIUM_XCUITEST_PREFER_DEVICECTLflag: -
If running Xcode
>= 26.1:-
Start a session with the additional
appium:wdaBaseUrlcapability, which must be set to the IP address of the Apple TV:{ "platformName": "tvOS", "appium:automationName": "XCUITest", "appium:udid": "<apple-tv-udid>", "appium:platformVersion": "<tvos-version>", "appium:wdaBaseUrl": "http://<apple-tv-ip-address>", ... }You can omit this capability if using the Preinstalled WDA approach.
-
-
If running Xcode
<= 26.0.1:-
Manually build and launch WebDriverAgentRunner (WDA) yourself. This can be done through the Xcode GUI or otherwise. You can also refer to the steps in the Run Preinstalled WDA guide.
-
Follow the Attach to Running WDA guide and start a session with the
appium:webDriverAgentUrlcapability.
-
Wireless tvOS 16 or Earlier¶
Such devices have not been officially tested, but user reports have shown that they are discoverable and automatable with the same real device requirements as iOS/iPadOS. You can therefore follow the Real Device Setup document, then start a session as normal:
{
"platformName": "tvOS",
"appium:automationName": "XCUITest",
"appium:udid": "<apple-tv-udid>",
"appium:platformVersion": "<tvos-version>",
...
}
Wired¶
Wired tvOS devices (Apple TV HD) use the same approach as iOS/iPadOS devices. Simply follow the Real Device Setup document, then start a session as normal:
{
"platformName": "tvOS",
"appium:automationName": "XCUITest",
"appium:udid": "<apple-tv-udid>",
"appium:platformVersion": "<tvos-version",
...
}
Session Actions¶
Unlike iOS/iPadOS, interactions with tvOS use remote controller
based actions. The XCUITest driver implements these actions using the
mobile: pressButton extension, with support
for over 10 different buttons. The menu button functions as a back button in the iOS context.
All actions are performed on the focused element (which has the focus attribute set). The
focused element is automatically changed after using mobile: pressButton.
It is also possible to use the standard findElement and click methods. The XCUITest driver will
automatically calculate the necessary sequence of up/down/left/right and select button presses,
so you should not care about which keys should be pressed to reach an arbitrary element every time.
You may want to consider using wait methods, since tvOS also has animation.
Here are a few example action sequences in different client languages:
WebElement element = driver.findElementByAccessibilityId("element on the app");
element.getAttribute("focused");
element.click();
driver.queryAppState("test.package.name");
driver.executeScript("mobile: pressButton", ImmutableMap.of("name", "Home"));
driver.executeScript("mobile: pressButton", ImmutableMap.of("name", "Up"));
element = driver.switchTo().activeElement();
element.getAttribute("label");
const element = $('element on the app');
element.getAttribute('focused');
element.click();
driver.queryAppState("test.package.name");
driver.execute('mobile: pressButton', {name: 'Home'});
driver.execute('mobile: pressButton', {name: 'Up'});
const activeElement = driver.getActiveElement();
activeElement.getAttribute('label');
element = driver.find_element_by_accessibility_id('element on the app')
element.get_attribute('focused')
element.click()
driver.query_app_state('test.package.name')
driver.execute_script('mobile: pressButton', { 'name': 'Home' })
driver.execute_script('mobile: pressButton', { 'name': 'Up' })
element = driver.switch_to.active_element
element.get_attribute('label')
element = @driver.find_element :accessibility_id, 'element on the app'
element.focused
element.click
@driver.app_state('test.package.name')
@driver.execute_script 'mobile: pressButton', { name: 'Home' }
@driver.execute_script 'mobile: pressButton', { name: 'Up' }
element = @driver.switch_to.active_element
element.label
Known Limitations¶
- Gesture commands do not work
- Certain commands such as pasteboard do not work
Related Tickets¶
- https://github.com/appium/appium/pull/12401
- https://github.com/appium/appium-xcuitest-driver/pull/911
- https://github.com/appium/appium-xcuitest-driver/pull/931
- https://github.com/appium/appium-xcuitest-driver/pull/939
- https://github.com/appium/WebDriverAgent/pull/163
- https://github.com/appium/appium-xcuitest-driver/pull/2194