Python API Release Notes#
Changes to the stbt core Python API are version-controlled. You can specify
the version you want to use in your .stbt.conf
file. See
test_pack.stbt_version in the Configuration
Reference.
We generally expect that upgrading to new versions will be safe; we strive to maintain backwards compatibility. But there may be some edge cases that affect some users, so this mechanism allows you to upgrade in a controlled manner, and to test the upgrade on a branch first.
v34#
14 June 2023
Changes in behaviour since v33:
Tests are run using pytest. Pytest provides many useful features, including detailed information about failing assertions, and fixtures for re-usable setup and teardown steps. In v33, pytest was optional; in v34 pytest is the default (and only) test-runner. To learn more about pytest see New features in v33: Pytest support.
stbt.load_image
,stbt.match
: Normalize the alpha (transparency) channel when loading numpy arrays, in the same way we normalize the alpha channel of a PNG image. Callingload_image
ormatch
with a numpy array now behaves the same as calling it with a PNG filename.stbt.match
: Don’t ignore the reference image’s alpha (transparency) channel ifframe
is a single-channel (grayscale) image. Previously the reference image was converted to grayscale before matching; now the frame is converted to color before matching. This is unlikely to affect any existing tests as grayscale frames are only created as a result of custom image processing.stbt.wait_for_motion
,stbt.detect_motion
,stbt.press_and_wait
,stbt.wait_for_transition_to_end
: MakeBGRDiff
the default diffing algorithm.The previous default (
GrayscaleDiff
) doesn’t detect changes that are different in color but of a similar overall intensity, such as the blue (focused) vs. white (unfocused) letters in this screenshot of the Xfinity on-screen keyboard.Note that the
noise_threshold
ofBGRDiff
is different in scale (it’s now 0-255 instead of 0.0-1.0) and in direction (a smaller number means a stricter threshold).BGRDiff
’s default threshold is 25, so it’s slightly stricter (GrayscaleDiff
’s threshold of 0.84 would correspond to roughly a value of 40 in theBGRDiff
algorithm).To continue using the previous algorithm, run the following code early in your test script (for example at the top level of
tests/__init__.py
):stbt.detect_motion.differ = stbt.GrayscaleDiff() stbt.press_and_wait.differ = stbt.GrayscaleDiff()
Note that the above 2 lines also affect
wait_for_motion
andwait_for_transition_to_end
.
Other new features and fixes:
New Smart Navigation functions
stbt.navigate_1d
andstbt.navigate_grid
.New integration with pyatv for sending commands to Apple TV devices over the network. See Apple TV for details.
stbt.Mask.from_alpha_channel
: New constructor for creating a Mask from a PNG image’s alpha (transparency) channel. Useful when you have a reference image with some transparent parts, but you want to use that same mask for an operation other thanmatch
.stbt.Mask.to_array
: If adding or subtracting masks results in an empty region, log a warning. Useful for debugging issues with the coordinates in your test script.stbt.press_and_wait
,stbt.wait_for_transition_to_end
: Addframes
parameter (consistent withwait_for_motion
). This allows performing custom transformations on the video (such as removing background behind a translucent overlay) before it’s processed by the motion detection ofpress_and_wait
.stbt.press_and_wait
: Addretries
parameter. If the keypress had no effect at all, retry this number of times. Defaults to 0, so you have to opt-in to this behaviour by specifying, for example,retries=1
orretries=2
.stbt.wait_until
: Log how long thewait_until
call took until it succeeded.
v33#
13 July 2022
Major new features:
v33 has a new test-runner environment based on Ubuntu 22.04 and Python 3.10. The most notable changes are:
Software
v32
v33
Ubuntu
18.04
22.04
Python
3.6
3.10
Tesseract (OCR engine)
4.00~git2288-10f4998a-2
4.1.1
OpenCV
3.2
4.5
Pylint
1.8
2.14
Pytest
3.3.2
6.2.5
ADB
8.1
29.0
Any third-party packages that you install using
apt
in your setup script may be upgraded to a newer version too.Python 2 is not supported. Customers who are still using Python 2 should continue using v32 or earlier. To upgrade see our guide: Porting a test-pack to Python 3.
Tests can optionally be run using pytest. Pytest provides many useful features, including detailed information about failing assertions, and fixtures for re-usable setup and teardown steps. For more details see New features in v33: Pytest support.
BDD-style test scripts are supported, using the pytest-bdd API. For more details see New features in v33: BDD support.
New
Mask
API to construct masks from regions. You can add, subtract or invert regions to construct a mask. This is much more convenient than creating a mask PNG in an image editor. See Regions and Masks for examples.Any API with a
mask
parameter can take a single Region, or a complex mask constructed from Regions as described above, or a filename of a black-and-white PNG image. Previously, themask
parameter could only take a filename.Any API that takes a color can take a web-style “#rrggbb” string (for example
"#f76600"
). Previously colors had to be specified as a(blue, green, red)
tuple of ints. Now both formats are accepted.stbt.find_regions_by_color
: New API to find any GUI element of a solid color (for example a button, or a “focus” or “selection” border).stbt.segment
: New API to find distinct foreground elements (such as lines of text). It’s pronounced like the verb (segMENT) not the noun.New
stbt.android
API for interacting with AndroidTV devices using ADB.New
stbt.Roku
API for interacting with Roku devices over the network using Roku’s External Control Protocol.stbt.find_file
: New API to resolve a filename relative to the python file that’s calling it. It uses the same search algorithm asstbt.load_image
, but it works with any type of file.stbt.MultiPress
: New API to enter text using a numeric keypad using the ITU-T E.161 mapping.
Changes in behaviour since v32:
Dropped support for Python 2.
Debug logging from stbt APIs uses Python’s logging framework. Each debug line now starts with the logger name and logging level (namely “DEBUG:stbt:”).
Reworked
stbt.android
API. Previously this was a private, undocumented API in_stbt.android
but a small number of customers were already using it. The changes are:Changed order & defaults of
AdbDevice
constructor arguments to make it more suitable for Android TV devices (as opposed to mobile devices).Made
AdbDevice.adb
more likesubprocess.run
.Support ADB host key committed to test-pack, to support stateless test-runners. From the root of your test-pack (git checkout) run
adb keygen config/android/adbkey
and commit theconfig/android
directory to git. Warning: Anyone with read access to your test-pack git repository and with network access to your AndroidTV devices will be able to control them using ADB.
stbt.find_selection_from_background
: Theregion
attribute of the return value is set even if it failed themax_size
/min_size
checks. Previouslyregion
would have beenNone
.If you have code like this:
@property def selection(self): return stbt.find_selection_from_background(...).region # Wrong in v33!
…rewrite it to this:
@property def selection(self): sel = stbt.find_selection_from_background(...) if sel: return sel.region
stbt.Keyboard
: Removed the first parameter of the constructor. Since v32 it would raise an exception if you passed this parameter, so nobody should be using it by now. All the remaining parameters must be specified by keyword.stbt.load_image
: The returned image is read only; call its copy() method to make a writeable copy if you need to modify it.
Deprecated APIs:
The
region
parameter ofis_screen_black
,detect_motion
,wait_for_motion
,press_and_wait
, andwait_for_transition_to_end
is deprecated. Pass your region to themask
parameter instead. For now, theregion
parameter is an alias ofmask
. Conceptually masks are a superset of regions.Note that functions that don’t accept an arbitrary mask (only a
Region
) still take aregion
parameter — namelymatch
and associated APIs,ocr
andmatch_text
,Keyboard.add_key
andKeyboard.find_key
.stbt.load_image
: Theflags
parameter is deprecated. Use thecolor_channels
parameter instead.
Minor additions, bugfixes & improvements:
stbt.Frame
andstbt.Image
:Add
width
,height
, andregion
properties.Fix IndexError in
__repr__
when the Frame or Image has undergone numpy operations that change its shape (such asnumpy.max
, which will preserve thestbt.Image
orstbt.Frame
type of its argument).
-
The object’s
__repr__
only prints the values of properties that have already been calculated. That is, it doesn’t trigger evaluation of all public properties.The
__repr__
shows the object’s frame (self._frame
) so you can see the timestamp of the frame associated with each FrameObject instance.Fix comparison operators (
==
and!=
). Previously they would raiseTypeError
if either operand had a property that returnedNone
; or they could return the wrong result if comparing an instance of a class F against an instance of F’s subclass.Remove ordering operators (
<
, etc). They were buggy and there’s no use-case for ordering Page Object instances.
stbt.RmsVolumeResult
: AddeddBov
method to convert the RMS amplitude to decibels.-
Added type
stbt.Keyboard.Key
: This is the type returned fromKeyboard.find_key
. Previously it was an opaque, private type; now it is a public, documented API. This is so that you can use it in type annotations for your FrameObject properties.Better support for slow/laggy keyboards:
Recover from missed or double keypresses by re-calculating the path from the current state of the device-under-test. To disable this behaviour specify
retries=0
when callingKeyboard.enter_text
orKeyboard.navigate_to
.retries
defaults to 2.Increased default
navigate_timeout
from 20 to 60.Wait longer for the selection to reach the final target when we’re not verifying every keypress.
Better error message when user’s Page Object’s
selection
property returnsNone
(it’s a bug in your Page Object if it saysis_visible==True
butselection==None
).
-
Cache the last 5 loaded images. This will avoid repeating the same PNG decoding for every frame when you do something like
stbt.wait_until(lambda: stbt.match("reference.png"))
.New
color_channels
parameter, replacingflags
which is now deprecated.Raise
FileNotFoundError
with the correct errno, instead ofIOError
without an errno. Note thatFileNotFoundError
is a subclass ofIOError
.Normalize the alpha channel (if any) so that each pixel is either fully transparent (0) or fully opaque (255). Previously this normalization was done in
stbt.match
.
stbt.match
: Fixed the position of the region drawn in the Object Repository “Debug” tool.stbt.ocr
:corrections
parameter: Fix matching non-word characters at word boundaries.stbt.press
: Thekey
argument can be an Enum (press
will use the Enum’s value, which must be a string).stbt.press_and_wait
: The return value has newstarted
,complete
, andstable
attributes. This is often clearer than checking the value of thestatus
attribute:transition = stbt.press_and_wait("KEY_OK") if not transition.started: ... # versus: # if transition.status == stbt.TransitionStatus.START_TIMEOUT:
stbt.Size
: New helper type. It’s a tuple withwidth
andheight
.pylint plugin: Increase Astroid’s inference limit to fix various false positives.
v32#
1 October 2020.
Warning
When upgrading the stb-tester package to v32 locally with pip
(for your
IDE) please follow these steps to uninstall the previous version first:
pip uninstall stb-tester stbt-premium-stubs stbt-extra-stubs
pip install stb-tester
Major new features:
stbt.Keyboard
: Support keyboards with multiple modes (for example lowercase, uppercase, and symbols).stbt.find_selection_from_background
: New function to detect if a page is visible, and simultaneously find the position of the current “selection” or “highlight” on the page.-
Calls to Tesseract are cached if all the parameters are identical (including all the pixels in the frame & region). This cache is persisted on disk between test-jobs. This can greatly speed up calls to
ocr
when reading common text, for example when navigating menus.New
corrections
parameter: A dict of {bad: good} mappings to correct known OCR mistakes.New function
stbt.apply_ocr_corrections
to apply the same corrections to any string — useful for post-processing old test artifacts using new corrections.New function
stbt.set_global_ocr_corrections
to specify the default value for ocr’scorrections
parameter. Call this early in your tests, for example in the top-level oftests/__init__.py
.
stbt.press_and_wait
: New parametermin_size
to ignore motion in small regions (useful when you can’t predict the exact position of those regions by specifying a mask).-
New
center
property that returns astbt.Position
value withx
andy
attributes.stbt.Region.contains
accepts astbt.Position
as the argument (previously it only accepted astbt.Region
).stbt.Region.translate
can take anotherstbt.Region
as its argument, instead of separatex
andy
coordinates.
stbt.detect_pages
: New function to find the Page Objects that are relevant for the current video frame.stbt.last_keypress
: New function that returns information about the last key-press sent to the device under test.stbt.stop_job
: New function to stop a job of multiple testcases or a soak-test.Pylint plugin new checker: Check that the return value from
FrameObject.refresh
is used (FrameObjects are immutable, sorefresh()
returns a new object instead of modifying the object it’s called on).
Changes in behaviour since v31:
stbt.crop
: Implicitly clamp at the edges of the frame, if the region extends beyond the frame. Previously, this would have raised an exception. It still raises ValueError if the region is entirely outside of the frame.stbt.draw_text
: Also write text to stderr.stbt.get_config
: AllowNone
as a default value.stbt.is_screen_black
: Increase default threshold from 10 to 20.-
Changed the internal representation of the Directed Graph. Manipulating the networkx graph directly is no longer supported.
Removed
Keyboard.parse_edgelist
andgrid_to_navigation_graph
. Instead, first create the Keyboard object, and then use itsadd_key
,add_transition
,add_edgelist
, andadd_grid
methods to build the model of the keyboard.Removed the
Keyboard.Selection
type. Instead, your Page Object’sselection
property should return a Key value obtained fromKeyboard.find_key
.The edgelist format now allows key names with “#” in them. Previously anything starting with “#” was treated as a comment. Now comments are lines starting with “###” (three hashes), optionally preceded by whitespace.
Keyboard.enter_text
adds a short inter-press delay when entering the same letter twice, because some keyboard implementations ignore the second keypress if pressed too quickly.
-
Fix UnicodeDecodeError when filename is utf8-encoded bytes.
Allow passing a numpy array.
Return type changed from
numpy.ndarray
tostbt.Image
, which is a sub-class ofnumpy.ndarray
with the additional attributesfilename
,relative_filename
, andabsolute_filename
.
stbt.match
: Disable the “pyramid” performance optimisation if the reference image has too few non-transparent pixels. This fixes false negatives when the reference image is mostly transparent (for example a thin border of opaque pixels around a large transparent centre).stbt.MatchResult
(the return value fromstbt.match
): Theimage
attribute is now an instance ofstbt.Image
. Previously it was a string or a numpy array, depending on what you had passed tostbt.match
.stbt.ocr
andstbt.match_text
: Ifregion
is entirely outside the frame, raise ValueError instead of returning an empty string. (This is likely to be an error in your test-script’s logic, not desired behaviour.) This is now consistent with all the other image-processing APIs such asstbt.match
.-
Now uses the same difference-detection algorithm as
stbt.wait_for_motion
. This algorithm is more tolerant of small noise-like differences (less than 3 pixels wide). To use the previous algorithm, run the following code early in your test script (for example at the top level oftests/__init__.py
):stbt.press_and_wait.differ = stbt.StrictDiff
If you were passing a numpy array for the
mask
parameter, now it needs to be a single-channel image (grayscale) not a 3-channel image (BGR). (But if you were passing the mask as the filename of an image on disk, you don’t need to change anything.)
v31#
19 September 2019.
Major new features:
Supports test-scripts written in Python 3. Python 2 is still supported, too. When upgrading your test-pack to v31 you will need to specify a Python version in your test-pack’s
.stbt.conf
file like this:[test_pack] stbt_version = 31 python_version = 3
Valid values are 2 or 3. The test-run environment is Ubuntu 18.04, so you get Python 2.7 or 3.6.
We recommend Python 3 for all new test-packs. For large existing test-packs we will continue to support Python 2 until all our large customers have migrated.
stbt.Keyboard
: New API for testing & navigating on-screen keyboards.stbt.Grid
: New API for describing grid-like layouts.
Minor additions, bugfixes & improvements:
stbt.match
: Fix false negative when usingMatchMethod.SQDIFF
and a reference image that is mostly transparent except around the edges (for example to find a “highlight” or “selection” around some dynamic content).stbt.match
: Improve error message when you give it an explicit region that is smaller than the reference image.stbt.ocr
: New parameterchar_whitelist
. Useful when you’re reading text of a specific format, like the time from a clock, a serial number, or a passcode.stbt.press_and_wait
: Ignore small moiré-like differences between frames (temporal dithering?) seen with Apple TV.stbt.press_and_wait
: Draw motion bounding-box on output video (similar tostbt.wait_for_motion
).stbt.press_and_wait
: Addkey
attribute (the name of the key that was pressed) to the return value.stbt.Region
: The static methodsintersect
andbounding_box
will fail if called on an instance. That is, instead of callingself.intersect(other)
you must callstbt.Region.intersect(self, other)
. Previously, if called on an instance it would silently return a wrong value.stbt.wait_for_motion
: More sensitive to slow motion (such as a slow fade to black) by comparing against the last frame since significant differences were seen, instead of always comparing against the previous frame.stbt lint improvements:
New checker
stbt-frame-object-get-frame
: FrameObject properties must useself._frame
, notstbt.get_frame()
.New checker
stbt-frame-object-property-press
: FrameObject properties must not have side-effects that change the state of the device-under-test by callingstbt.press()
orstbt.press_and_wait()
.New checker
stbt-assert-true
: “assert True” has no effect.Teach pylint that
assert False
is the same asraise AssertionError
. This fixes incorrect behaviour of pylint’s “unreachable code” and “inconsistent return statements” checkers.
v30#
25 February 2019.
Minimum version supported by the Stb-tester Platform.