Smart TV Testing
Run tests on physical Smart TV devices with TestingBot, using the open-source test framework Appium.
Currently TestingBot supports running automated tests on physical AppleTV 4k devices.
To get started with testing your Smart TV app in the cloud, you will need to follow these steps:
- Upload your native Smart TV app, either to a public URL or using TestingBot Storage.
- Create an Appium test script that will connect to TestingBot.
- The results will be available in the TestingBot dashboard, together with a video of the test and logs.
Upload Smart TV App
To run Smart TV tests on TestingBot, you will first have to upload your .ipa
file to TestingBot Storage.
More information regarding this API call and other similar calls (update uploaded file, delete uploaded file, list uploaded files) are available in the TestingBot API documentation.
Note: uploads to TestingBot Storage are automatically deleted after 62 days.
Run your first SmartTV test
Once you've uploaded your Smart TV app, you can start with running your first test on the TestingBot SmartTV cloud.
TestingBot currently only supports running tests on physical AppleTV 4k devices. Please see the example tests below, where we use the TestingBot tvOS example app to input two numbers in the calculator and verify its sum.
require 'rubygems'
require 'appium_lib'
caps = {}
caps['name'] = 'Ruby tvOS Example'
caps['deviceName'] = 'Apple TV 4K'
caps['platformName'] = 'tvOS'
caps['version'] = '17.4'
caps['app'] = 'https://github.com/testingbot/tvos-example/releases/download/1.0.0/tvos-example.ipa'
caps['realDevice'] = true
appium_driver = Appium::Driver.new({
caps: caps,
appium_lib: {
server_url: "https://key:secret@hub.testingbot.com/wd/hub"
}}, true)
driver = appium_driver.start_driver
wait = Selenium::WebDriver::Wait.new(:timeout => 30)
wait.until { driver.find_element(:accessibility_id, "inputField1").displayed? }
inputField1 = driver.find_element(:accessibility_id, "inputField1")
inputField1.click
inputField1.send_keys 5
driver.execute_script('mobile: pressButton', { name: 'down' })
driver.execute_script('mobile: pressButton', { name: 'select' })
driver.switch_to.active_element.send_keys 10
driver.execute_script('mobile: pressButton', { name: 'down' })
driver.execute_script('mobile: pressButton', { name: 'select' })
result = driver.find_element(:accessibility_id, "resultField")
if (!result.nil?) && (result.text.to_i == 15)
puts "Test Passed"
else
puts "Test Failed"
end
driver.quit
const wdio = require('webdriverio');
const caps = {
name: 'Node.js tvOS Example',
deviceName: 'Apple TV 4K',
platformName: 'tvOS',
platformVersion: '17.4',
app: 'https://github.com/testingbot/tvos-example/releases/download/1.0.0/tvos-example.ipa',
realDevice: true
};
const options = {
protocol: 'https',
hostname: 'hub.testingbot.com',
port: 443,
path: '/wd/hub',
user: 'key', // Replace 'key' with your TestingBot key
key: 'secret', // Replace 'secret' with your TestingBot secret
capabilities: caps
};
(async () => {
// Start the Appium driver
const driver = await wdio.remote(options);
try {
// Wait for the first input field to be displayed
const inputField1 = await driver.$('~inputField1');
await inputField1.waitForDisplayed({ timeout: 30000 });
// Interact with the first input field
await inputField1.click();
await inputField1.setValue(5);
// Navigate down and select
await driver.execute('mobile: pressButton', { name: 'down' });
await driver.execute('mobile: pressButton', { name: 'select' });
// Send keys to the active element
await driver.switchToParentFrame(); // Ensure focus is on the active frame
await driver.activeElement().setValue(10);
// Navigate down and select the result
await driver.execute('mobile: pressButton', { name: 'down' });
await driver.execute('mobile: pressButton', { name: 'select' });
// Verify the result
const result = await driver.$('~resultField');
const resultText = await result.getText();
if (resultText && parseInt(resultText, 10) === 15) {
console.log('Test Passed');
} else {
console.log('Test Failed');
}
} catch (err) {
console.error('Error occurred:', err);
} finally {
// Quit the driver
await driver.deleteSession();
}
})();
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# Define capabilities
caps = {
"name": "Python tvOS Example",
"deviceName": "Apple TV 4K",
"platformName": "tvOS",
"platformVersion": "17.4",
"app": "https://github.com/testingbot/tvos-example/releases/download/1.0.0/tvos-example.ipa",
"realDevice": True
}
# Appium server URL
server_url = "https://key:secret@hub.testingbot.com/wd/hub"
# Initialize the driver
driver = webdriver.Remote(server_url, caps)
try:
# Wait for the first input field to be displayed
wait = WebDriverWait(driver, 30)
input_field1 = wait.until(EC.presence_of_element_located((By.ACCESSIBILITY_ID, "inputField1")))
# Interact with the first input field
input_field1.click()
input_field1.send_keys("5")
# Navigate down and select the second input field
driver.execute_script('mobile: pressButton', {'name': 'down'})
driver.execute_script('mobile: pressButton', {'name': 'select'})
# Send keys to the active element (second input field)
driver.switch_to.active_element.send_keys("10")
# Navigate down and select the result field
driver.execute_script('mobile: pressButton', {'name': 'down'})
driver.execute_script('mobile: pressButton', {'name': 'select'})
# Verify the result
result_field = driver.find_element(By.ACCESSIBILITY_ID, "resultField")
result_text = result_field.text
if result_text and int(result_text) == 15:
print("Test Passed")
else:
print("Test Failed")
except Exception as e:
print(f"An error occurred: {e}")
finally:
# Quit the driver
driver.quit()
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileBy;
import io.appium.java_client.remote.MobileCapabilityType;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.net.URL;
import java.time.Duration;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class TvOSTest {
public static void main(String[] args) {
AppiumDriver<WebElement> driver = null;
try {
// Set capabilities
DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability("name", "Java tvOS Example");
caps.setCapability("deviceName", "Apple TV 4K");
caps.setCapability("platformName", "tvOS");
caps.setCapability("platformVersion", "17.4");
caps.setCapability("app", "https://github.com/testingbot/tvos-example/releases/download/1.0.0/tvos-example.ipa");
caps.setCapability("realDevice", true);
URL serverUrl = new URL("https://key:secret@hub.testingbot.com/wd/hub");
driver = new AppiumDriver<>(serverUrl, caps);
// Wait for the first input field to be displayed
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30));
WebElement inputField1 = wait.until(ExpectedConditions.presenceOfElementLocated(MobileBy.AccessibilityId("inputField1")));
inputField1.click();
inputField1.sendKeys("5");
// Navigate down and select the second input field
driver.executeScript("mobile: pressButton", Map.of("name", "down"));
driver.executeScript("mobile: pressButton", Map.of("name", "select"));
// Send keys to the active element (second input field)
WebElement activeElement = driver.switchTo().activeElement();
activeElement.sendKeys("10");
// Navigate down and select the result field
driver.executeScript("mobile: pressButton", Map.of("name", "down"));
driver.executeScript("mobile: pressButton", Map.of("name", "select"));
WebElement resultField = driver.findElement(MobileBy.AccessibilityId("resultField"));
String resultText = resultField.getText();
if (resultText != null && Integer.parseInt(resultText) == 15) {
System.out.println("Test Passed");
} else {
System.out.println("Test Failed");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// Quit the driver
if (driver != null) {
driver.quit();
}
}
}
}
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Enums;
using OpenQA.Selenium.Appium.iOS;
using OpenQA.Selenium.Support.UI;
using System;
using System.Collections.Generic;
class TvOSTest
{
static void Main(string[] args)
{
AppiumDriver<IWebElement> driver = null;
try
{
// Set capabilities
var caps = new AppiumOptions();
caps.AddAdditionalCapability(MobileCapabilityType.PlatformName, "tvOS");
caps.AddAdditionalCapability(MobileCapabilityType.DeviceName, "Apple TV 4K");
caps.AddAdditionalCapability(MobileCapabilityType.PlatformVersion, "17.4");
caps.AddAdditionalCapability(MobileCapabilityType.App, "https://github.com/testingbot/tvos-example/releases/download/1.0.0/tvos-example.ipa");
caps.AddAdditionalCapability("realDevice", true);
caps.AddAdditionalCapability("name", "C# tvOS Example");
// Initialize driver
var serverUri = new Uri("https://key:secret@hub.testingbot.com/wd/hub");
driver = new IOSDriver<IWebElement>(serverUri, caps);
// Wait for the first input field to be displayed
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
var inputField1 = wait.Until(d => d.FindElement(MobileBy.AccessibilityId("inputField1")));
// Interact with the first input field
inputField1.Click();
inputField1.SendKeys("5");
// Navigate down and select the second input field
driver.ExecuteScript("mobile: pressButton", new Dictionary<string, string> { { "name", "down" } });
driver.ExecuteScript("mobile: pressButton", new Dictionary<string, string> { { "name", "select" } });
// Send keys to the active element (second input field)
var activeElement = driver.SwitchTo().ActiveElement();
activeElement.SendKeys("10");
// Navigate down and select the result field
driver.ExecuteScript("mobile: pressButton", new Dictionary<string, string> { { "name", "down" } });
driver.ExecuteScript("mobile: pressButton", new Dictionary<string, string> { { "name", "select" } });
// Verify the result
var resultField = driver.FindElement(MobileBy.AccessibilityId("resultField"));
var resultText = resultField.Text;
if (!string.IsNullOrEmpty(resultText) && int.Parse(resultText) == 15)
{
Console.WriteLine("Test Passed");
}
else
{
Console.WriteLine("Test Failed");
}
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
finally
{
// Quit the driver
driver?.Quit();
}
}
}
View SmartTV Test Results
Once your test has finished running, you will see a new test entry in the TestingBot dashboard.. If you click the test, you will see detailed information about the test, including a video recording of the test, logs and screenshots.
You can also use the TestingBot API to programmatically fetch the test results.