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. Calling load_image or match 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 if frame 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: Make BGRDiff 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 of BGRDiff 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 the BGRDiff 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 and wait_for_transition_to_end.

Other new features and fixes:

  • New Smart Navigation functions stbt.navigate_1d and stbt.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 than match.

  • 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: Add frames parameter (consistent with wait_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 of press_and_wait.

  • stbt.press_and_wait: Add retries 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 or retries=2.

  • stbt.wait_until: Log how long the wait_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, the mask 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 as stbt.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 like subprocess.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 the config/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: The region attribute of the return value is set even if it failed the max_size / min_size checks. Previously region would have been None.

    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:

Minor additions, bugfixes & improvements:

  • stbt.Frame and stbt.Image:

    • Add width, height, and region properties.

    • Fix IndexError in __repr__ when the Frame or Image has undergone numpy operations that change its shape (such as numpy.max, which will preserve the stbt.Image or stbt.Frame type of its argument).

  • stbt.FrameObject:

    • 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 raise TypeError if either operand had a property that returned None; 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: Added dBov method to convert the RMS amplitude to decibels.

  • stbt.Keyboard:

    • Added type stbt.Keyboard.Key: This is the type returned from Keyboard.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 calling Keyboard.enter_text or Keyboard.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 returns None (it’s a bug in your Page Object if it says is_visible==True but selection==None).

  • stbt.load_image:

    • 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, replacing flags which is now deprecated.

    • Raise FileNotFoundError with the correct errno, instead of IOError without an errno. Note that FileNotFoundError is a subclass of IOError.

    • 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: The key 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 new started, complete, and stable attributes. This is often clearer than checking the value of the status 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 with width and height.

  • pylint plugin: Increase Astroid’s inference limit to fix various false positives.

v32#

1 October 2020.

Minimum version supported by the Stb-tester Platform.