Selenium for second-screen login flows#
You can use Selenium to automate browser-based user journeys on a second screen, from the same Stb-tester Python script that is automating the big screen journey. For example, many TV apps use a browser-based login flow, where the TV screen shows a code that you type into a browser on your phone or computer.
Recipe#
Create a config/setup/setup
script to install Selenium and a browser
(Chromium):
#!/bin/bash -ex
# Install Chromium and Selenium — see https://stb-tester.com/manual/selenium
sudo apt-get update
mkdir -p /tmp/chromium
cd /tmp/chromium
curl --fail \
-O https://deb.debian.org/debian/pool/main/c/chromium/chromium_120.0.6099.224-1~deb11u1_arm64.deb \
-O https://deb.debian.org/debian/pool/main/c/chromium/chromium-common_120.0.6099.224-1~deb11u1_arm64.deb \
-O https://deb.debian.org/debian/pool/main/c/chromium/chromium-driver_120.0.6099.224-1~deb11u1_arm64.deb \
-O https://deb.debian.org/debian/pool/main/libj/libjpeg-turbo/libjpeg62-turbo_2.0.6-4_arm64.deb \
-O https://deb.debian.org/debian/pool/main/libj/libjsoncpp/libjsoncpp24_1.9.4-4_arm64.deb \
-O https://deb.debian.org/debian/pool/main/libw/libwebp/libwebp6_0.6.1-2.1%2Bdeb11u2_arm64.deb
ls -l
sudo apt-get install -y ./*.deb
cd -
rm -rf /tmp/chromium
sudo pip3 install selenium==4.31.0
From your Python tests, use Selenium WebDriver like this:
import selenium.webdriver
from selenium.webdriver.chromium.service import ChromiumService
options = selenium.webdriver.ChromeOptions()
options.add_argument("--headless=new")
service = ChromiumService("/usr/bin/chromedriver")
webdriver = selenium.webdriver.Chrome(options=options, service=service)
webdriver.get("https://example.com")
Demo#
In this short demo we sign into the BBC iPlayer app. We use Stb-tester’s ocr API to read the sign-in code from the TV screen, and enter it into the browser using Selenium.
Details#
The config/setup/setup
script in your test-pack git repository
is used to install any third-party packages or dependencies that are not
installed on the Stb-tester Node by default. See Customising the test-run environment.
Breaking it down:
#!/bin/bash -ex
This is a Bash shell script; the -e
option means that the script will fail
immediately if any of the commands in the script fail. This is important so
that Stb-tester can detect when the environment wasn’t built correctly.
The -x
option means that each command is printed to the log before it is
executed; this is useful for debugging issues with the script.
sudo apt-get update
mkdir -p /tmp/chromium
cd /tmp/chromium
curl --fail \
-O https://deb.debian.org/debian/pool/main/c/chromium/chromium_120.0.6099.224-1~deb11u1_arm64.deb \
-O https://deb.debian.org/debian/pool/main/c/chromium/chromium-common_120.0.6099.224-1~deb11u1_arm64.deb \
-O https://deb.debian.org/debian/pool/main/c/chromium/chromium-driver_120.0.6099.224-1~deb11u1_arm64.deb \
-O https://deb.debian.org/debian/pool/main/libj/libjpeg-turbo/libjpeg62-turbo_2.0.6-4_arm64.deb \
-O https://deb.debian.org/debian/pool/main/libj/libjsoncpp/libjsoncpp24_1.9.4-4_arm64.deb \
-O https://deb.debian.org/debian/pool/main/libw/libwebp/libwebp6_0.6.1-2.1%2Bdeb11u2_arm64.deb
sudo apt-get install -y ./*.deb
cd -
rm -rf /tmp/chromium
The above commands download & install the Chromium packages from Debian. Stb-tester v34 uses Ubuntu 22.04, and this (Chromium 120, which was released January 2024) is the latest version in Debian that is compatible with Ubuntu 22.04 (the newer Chromium packages need a newer libc etc).
This also downloads some of Chromium’s dependencies (libjpeg62-turbo, libjsoncpp24, libwebp6) that aren’t available in Ubuntu 22.04.
We install Chromium from Debian (instead of Chrome from Google) because Google doesn’t provide Chrome packages for the ARM64 architecture of the Stb-tester Node.
sudo pip3 install selenium==4.31.0
This installs the selenium
Python package. We specify an exact version to
ensure reproducible builds of the test environment: Every time we run this
script, we want the output to be identical. 4.31.0 was the latest version as of
this writing.
Now, on to how we use Selenium in our Python tests:
import selenium.webdriver
from selenium.webdriver.chromium.service import ChromiumService
options = selenium.webdriver.ChromeOptions()
options.add_argument("--headless=new")
service = ChromiumService("/usr/bin/chromedriver")
webdriver = selenium.webdriver.Chrome(options=options, service=service)
--headless=new
is a command-line option given to Chromium. Without it,
Chromium fails to start because there is no display attached to the test
environment on the Stb-tester Node.
Normally Selenium uses selenium-manager to find where the chromedriver
executable is installed, but selenium-manager doesn’t support the ARM64
architecture. We can bypass it by specifying the path to chromedriver
explicitly.
From here on, webdriver
is a normal Selenium WebDriver object. You can call
get, find_element, etc. For example,
in the demo above we used it like this:
webdriver.get("https://bbc.com/account/tv")
pin_field = webdriver.find_element(By.CSS_SELECTOR, "input#pin")
pin_field.send_keys(page.code)
pin_field.submit()
login_field = webdriver.find_element(By.CSS_SELECTOR,
"input#user-identifier-input")
login_field.send_keys(USERNAME)
login_field.submit()
password_field = webdriver.find_element(By.CSS_SELECTOR,
"input#password-input")
password_field.send_keys(PASSWORD)
password_field.submit()
References and further reading#
Customising the test-run environment in the Stb-tester manual.
Storing passwords and other secrets in the Stb-tester manual.
selenium
Python API: unofficial docs (better API overview), official API reference.docker-selenium Dockerfile (where I found the instructions for installing Chromium from Debian).
How to bypass selenium-manager (stackoverflow).