Esempio n. 1
0
    def swipe(self, start_position, end_position):
        """Swipe from one point to another point.

        :param start_position:
            A `stbt.Region` or (x, y) tuple of coordinates at which to start.
        :param end_position:
            A `stbt.Region` or (x, y) tuple of coordinates at which to stop.

        Example::

          d.swipe((100, 100), (100, 400))

        """
        x1, y1 = _region_to_tuple(start_position)
        x2, y2 = _region_to_tuple(end_position)
        stbt.debug("AdbDevice.swipe((%d,%d), (%d,%d))" % (x1, y1, x2, y2))

        x1, y1 = self._to_native_coordinates(x1, y1)
        x2, y2 = self._to_native_coordinates(x2, y2)
        command = [
            "shell", "input", "swipe",
            str(x1),
            str(y1),
            str(x2),
            str(y2)
        ]
        self.adb(command, timeout_secs=10)
Esempio n. 2
0
def main(argv):
    parser = _stbt.core.argparser()
    parser.prog = 'stbt record'
    parser.description = 'Create an stb-tester test script'
    parser.add_argument(
        '--control-recorder',
        default=stbt.get_config('record', 'control_recorder'),
        help='The source of remote control keypresses (default: %(default)s)')
    parser.add_argument(
        '-o', '--output-file',
        default=stbt.get_config('record', 'output_file'),
        help='The filename of the generated script (default: %(default)s)')
    args = parser.parse_args(argv[1:])
    stbt.debug("Arguments:\n" + "\n".join([
        "%s: %s" % (k, v) for k, v in args.__dict__.items()]))

    try:
        script = open(args.output_file, 'w')
    except IOError as e:
        e.strerror = "Failed to write to output-file '%s': %s" % (
            args.output_file, e.strerror)
        raise

    with _stbt.core.new_device_under_test_from_config(args) as dut:
        record(dut, args.control_recorder, script)
Esempio n. 3
0
def find_player(selected_image, unselected_image):
    """Navigates to the specified player.

    Precondition: In the OnDemand Players screen.

    Uses `unselected_image` to find where the player is on screen;
    navigates there;
    uses `selected_image` to know that it has reached the player.
    """

    page_changes = [0]
    def next_page():
        if page_changes[0] < 3:
            stbt.press("FASTFORWARD")
            time.sleep(1)
            page_changes[0] += 1
        else:
            raise stbt.MatchTimeout(None, unselected_image, 0)

    while not _player_selected(selected_image):
        target = stbt.detect_match(unselected_image).next()
        if target.match:
            source = _matches("images/any-player-selected.png").next()
            stbt.debug("find_player: source=%d,%d target=%d,%d" % (
                    source.position.x, source.position.y,
                    target.position.x, target.position.y))
            stbt.press(_next_key(source.position, target.position))
            _wait_for_selection_to_move(source)
        else:
            next_page()
Esempio n. 4
0
def main(argv):
    parser = _stbt.core.argparser()
    parser.prog = 'stbt run'
    parser.description = 'Run an stb-tester test script'
    parser.add_argument(
        '--save-screenshot', default='on-failure',
        choices=['always', 'on-failure', 'never'],
        help="Save a screenshot at the end of the test to screenshot.png")
    parser.add_argument(
        '--save-thumbnail', default='never',
        choices=['always', 'on-failure', 'never'],
        help="Save a thumbnail at the end of the test to thumbnail.jpg")
    parser.add_argument(
        'script', metavar='FILE[::TESTCASE]', help=(
            "The python test script to run. Optionally specify a python "
            "function name to run that function; otherwise only the script's "
            "top-level will be executed."))
    parser.add_argument(
        'args', nargs=argparse.REMAINDER, metavar='ARG',
        help='Additional arguments passed on to the test script (in sys.argv)')

    args = parser.parse_args(argv[1:])
    stbt.debug("Arguments:\n" + "\n".join([
        "%s: %s" % (k, v) for k, v in args.__dict__.items()]))

    dut = _stbt.core.new_device_under_test_from_config(args)
    with sane_unicode_and_exception_handling(args.script), video(args, dut):
        test_function = load_test_function(args.script, args.args)
        test_function.call()
Esempio n. 5
0
def main(argv):
    parser = _stbt.core.argparser()
    parser.prog = 'stbt record'
    parser.description = 'Create an stb-tester test script'
    parser.add_argument(
        '--control-recorder',
        default=stbt.get_config('record', 'control_recorder'),
        help='The source of remote control keypresses (default: %(default)s)')
    parser.add_argument(
        '-o',
        '--output-file',
        default=stbt.get_config('record', 'output_file'),
        help='The filename of the generated script (default: %(default)s)')
    args = parser.parse_args(argv[1:])
    stbt.debug("Arguments:\n" +
               "\n".join(["%s: %s" % (k, v)
                          for k, v in args.__dict__.items()]))

    try:
        script = open(args.output_file, 'w')
    except IOError as e:
        e.strerror = "Failed to write to output-file '%s': %s" % (
            args.output_file, e.strerror)
        raise

    with _stbt.core.new_device_under_test_from_config(args) as dut:
        record(dut, args.control_recorder, script)
Esempio n. 6
0
 def text(self):
     if self._text is None and self.__nonzero__():
         diff = cv2.cvtColor(
             cv2.absdiff(
                 crop(self._frame, self.region),
                 numpy.repeat(self._background, self.region.width, 1)),
             cv2.COLOR_BGR2GRAY)
         self._text = stbt.ocr(diff)
     stbt.debug("Selection text: %s" % self._text)
     return self._text
Esempio n. 7
0
 def _read_text(self, title, patterns=None):
     title = stbt.match_text(
         title, frame=self._frame,
         region=stbt.Region(x=620, y=145, right=950, bottom=460),
         text_color=(124, 94, 114))
     if not title:
         stbt.debug("NetworkAbout: Didn't find %r" % title)
         return None
     region = title.region.right_of().extend(x=10, y=-5, bottom=10)
     return stbt.ocr(self._frame, region, tesseract_user_patterns=patterns)
Esempio n. 8
0
 def text(self):
     if self._text is None and self.__nonzero__():
         diff = cv2.cvtColor(
             cv2.absdiff(
                 crop(self._frame, self.region),
                 numpy.repeat(self._background, self.region.width, 1)),
             cv2.COLOR_BGR2GRAY)
         self._text = stbt.ocr(diff)
     stbt.debug("Selection text: %s" % self._text)
     return self._text
Esempio n. 9
0
 def _read_text(self, title, patterns=None):
     title = stbt.match_text(
         title, frame=self._frame,
         region=stbt.Region(x=620, y=145, right=950, bottom=460),
         text_color=(124, 94, 114))
     if not title:
         stbt.debug("NetworkAbout: Didn't find %r" % title)
         return None
     region = title.region.right_of().extend(x=10, y=-5, bottom=10)
     return stbt.ocr(self._frame, region, tesseract_user_patterns=patterns)
Esempio n. 10
0
 def _adb(self, command, timeout_secs=None, **kwargs):
     _command = []
     if timeout_secs is not None:
         _command += ["timeout", "%fs" % timeout_secs]
     _command += [self.adb_binary]
     if self.adb_server:
         _command += ["-H", self.adb_server]
     if self.adb_device:
         _command += ["-s", self.adb_device]
     _command += command
     stbt.debug("AdbDevice.adb: About to run command: %r\n" % _command)
     output = subprocess.check_output(
         _command, stderr=subprocess.STDOUT, **kwargs)
     return output
Esempio n. 11
0
 def _adb(self, command, timeout_secs=None, **kwargs):
     _command = []
     if timeout_secs is not None:
         _command += ["timeout", "%fs" % timeout_secs]
     _command += [self.adb_binary]
     if self.adb_server:
         _command += ["-H", self.adb_server]
     if self.adb_device:
         _command += ["-s", self.adb_device]
     _command += command
     stbt.debug("AdbDevice.adb: About to run command: %r\n" % _command)
     output = subprocess.check_output(
         _command, stderr=subprocess.STDOUT, **kwargs)
     return output
Esempio n. 12
0
    def press(self, key):
        """Send a keypress.

        :param str key: An Android keycode as listed in
            <https://developer.android.com/reference/android/view/KeyEvent.html>.
            Particularly useful key codes are "KEYCODE_HOME" and
            "KEYCODE_BACK", which are physical buttons on some phones so you
            can't hit them with `AdbDevice.tap`.
        """
        # "adb shell input keyevent xxx" always returns success, so we need to
        # validate key names.
        if key not in _KEYCODES:
            raise ValueError("Unknown key code %r" % (key,))
        stbt.debug("AdbDevice.press(%r)" % key)
        self.adb(["shell", "input", "keyevent", key], timeout_secs=10)
Esempio n. 13
0
    def press(self, key):
        """Send a keypress.

        :param str key: An Android keycode as listed in
            <https://developer.android.com/reference/android/view/KeyEvent.html>.
            Particularly useful key codes are "KEYCODE_HOME" and
            "KEYCODE_BACK", which are physical buttons on some phones so you
            can't hit them with `AdbDevice.tap`.
        """
        # "adb shell input keyevent xxx" always returns success, so we need to
        # validate key names.
        if key not in _KEYCODES:
            raise ValueError("Unknown key code %r" % (key, ))
        stbt.debug("AdbDevice.press(%r)" % key)
        self.adb(["shell", "input", "keyevent", key], timeout_secs=10)
Esempio n. 14
0
    def tap(self, position):
        """Tap on a particular location.

        :param position: A `stbt.Region`, or an (x,y) tuple.

        Example::

            d.tap((100, 20))
            d.tap(stbt.match(...).region)

        """
        x, y = _region_to_tuple(position)
        stbt.debug("AdbDevice.tap((%d,%d))" % (x, y))

        x, y = self._to_native_coordinates(x, y)
        self.adb(["shell", "input", "tap", str(x), str(y)], timeout_secs=10)
Esempio n. 15
0
    def tap(self, position):
        """Tap on a particular location.

        :param position: A `stbt.Region`, or an (x,y) tuple.

        Example::

            d.tap((100, 20))
            d.tap(stbt.match(...).region)

        """
        x, y = _region_to_tuple(position)
        stbt.debug("AdbDevice.tap((%d,%d))" % (x, y))

        x, y = self._to_native_coordinates(x, y)
        self.adb(["shell", "input", "tap", str(x), str(y)], timeout_secs=10)
Esempio n. 16
0
    def swipe(self, start_position, end_position):
        """Swipe from one point to another point.

        :param start_position:
            A `stbt.Region` or (x, y) tuple of coordinates at which to start.
        :param end_position:
            A `stbt.Region` or (x, y) tuple of coordinates at which to stop.

        Example::

          d.swipe((100, 100), (100, 400))

        """
        x1, y1 = _region_to_tuple(start_position)
        x2, y2 = _region_to_tuple(end_position)
        stbt.debug("AdbDevice.swipe((%d,%d), (%d,%d))" % (x1, y1, x2, y2))

        x1, y1 = self._to_native_coordinates(x1, y1)
        x2, y2 = self._to_native_coordinates(x2, y2)
        command = ["shell", "input", "swipe",
                   str(x1), str(y1), str(x2), str(y2)]
        self.adb(command, timeout_secs=10)
Esempio n. 17
0
    def select(self, menu, *submenus):
        """Select the specified menu item (and sub-menus, if specified).

        Example::

            Menu().select("Settings", "Network", "About")

        """
        assert self.is_visible
        original_value = self.selection
        f = self  # FrameObject of current video-frame being processed
        target = menu
        for _ in range(20):
            assert f.is_visible
            current_value = f.selection
            if current_value == target:
                stbt.debug("Menu.select: Found %s" % target)
                if submenus:
                    transition = stbt.press_and_wait("KEY_OK")
                    assert transition
                    f = Menu(frame=transition.frame)
                    assert f.selection != current_value
                    return f.select(submenus[0], *submenus[1:])
                else:
                    return f
            stbt.debug("Menu.select: target=%r, current=%r, "
                       "going to press KEY_DOWN"
                       % (target, current_value))
            transition = stbt.press_and_wait("KEY_DOWN")
            assert transition
            f = Menu(frame=transition.frame)
            assert f.is_visible
            assert f.selection != current_value
            assert f.selection != original_value, (
                "Menu.select wrapped around to %r without finding %r"
                % (original_value, target))
Esempio n. 18
0
    def select(self, menu, *submenus):
        """Select the specified menu item (and sub-menus, if specified).

        Example::

            Menu().select("Settings", "Network", "About")

        """
        assert self.is_visible
        original_value = self.selection
        f = self  # FrameObject of current video-frame being processed
        target = menu
        for _ in range(20):
            assert f.is_visible
            current_value = f.selection
            if current_value == target:
                stbt.debug("Menu.select: Found %s" % target)
                if submenus:
                    transition = stbt.press_and_wait("KEY_OK")
                    assert transition
                    f = Menu(frame=transition.frame)
                    assert f.selection != current_value
                    return f.select(submenus[0], *submenus[1:])
                else:
                    return f
            stbt.debug("Menu.select: target=%r, current=%r, "
                       "going to press KEY_DOWN"
                       % (target, current_value))
            transition = stbt.press_and_wait("KEY_DOWN")
            assert transition
            f = Menu(frame=transition.frame)
            assert f.is_visible
            assert f.selection != current_value
            assert f.selection != original_value, (
                "Menu.select wrapped around to %r without finding %r"
                % (original_value, target))
Esempio n. 19
0
def find_selection_horizontal_repeat(
        frame, background, region=stbt.Region.ALL, match_threshold=0.95):

    """Find the selected menu item by looking for the specified background.

    This is an example to demonstrate that you can implement your own custom
    image processing with OpenCV.

    :param frame: An OpenCV image, as returned by `stbt.get_frame` or
        `cv2.imread`. If `None`, will pull a new frame from the system under
        test.

    :param background: The path to a 1-pixel-wide image of your
        system-under-test's menu selection/highlight.

    :param region: If specified, restrict the search to this region of the
        frame.

    :returns: A `Selection` object representing the selected item.

    Example::

        >>> frame = load_image("selftest-screenshots/roku-home.png")
        >>> find_selection_horizontal_repeat(
        ...     frame, "images/roku-menu-selection-background.png")
        Selection(region=Region(x=119, y=162, right=479, bottom=204),
                  text=u'Home')

    """

    if frame is None:
        frame = stbt.get_frame()
    frame = crop(frame, region)

    bg = load_image(background)

    correlation = 1 - cv2.matchTemplate(frame, bg, cv2.TM_SQDIFF_NORMED)
    _, max_, _, _ = cv2.minMaxLoc(correlation)
    selection_region = None
    if max_ >= match_threshold:
        # Find y coordinate
        rowmax = numpy.amax(correlation, axis=1)
        goodness = rowmax
        _, _, _, maxloc = cv2.minMaxLoc(goodness)
        y = maxloc[1]

        # Got the y position, now work out the horizontal extents
        line_uint8 = numpy.uint8(correlation[y, :]*255)
        _, binary = cv2.threshold(line_uint8, 0, 255,
                                  cv2.THRESH_OTSU | cv2.THRESH_BINARY)
        binary = binary.flatten()

        nonzeros = list(_combine_neighbouring_extents(
            list(_zeros_to_extents(binary.nonzero()[0]))))
        if nonzeros:
            widest = max(nonzeros, key=lambda a: a[1] - a[0])
            x, right = widest
            selection_region = (
                stbt.Region(x, y, right=right, bottom=y + bg.shape[0])
                .translate(x=max(0, region.x), y=max(0, region.y)))
            if selection_region.width > 10:
                # Remove the rounded corners of the selection; after subtracting
                # the background they look like single-quotes to the OCR engine.
                selection_region = selection_region.extend(x=5, right=-5)

    if not selection_region:
        stbt.debug(
            "find_selection didn't find match (%.2f) above the threshold (%.2f)"
            % (max_, match_threshold))

    return Selection(selection_region, frame, bg)
Esempio n. 20
0
def find_selection_horizontal_repeat(frame,
                                     background,
                                     region=stbt.Region.ALL,
                                     match_threshold=0.95):
    """Find the selected menu item by looking for the specified background.

    This is an example to demonstrate that you can implement your own custom
    image processing with OpenCV.

    :param frame: An OpenCV image, as returned by `stbt.get_frame` or
        `cv2.imread`. If `None`, will pull a new frame from the system under
        test.

    :param background: The path to a 1-pixel-wide image of your
        system-under-test's menu selection/highlight.

    :param region: If specified, restrict the search to this region of the
        frame.

    :returns: A `Selection` object representing the selected item.

    Example::

        >>> frame = load_image("../selftest/screenshots/roku-home.png")
        >>> find_selection_horizontal_repeat(
        ...     frame, "images/roku-menu-selection-background.png")
        Selection(region=Region(x=116, y=157, right=483, bottom=208),
                  text=u'Home')

    """

    if frame is None:
        frame = stbt.get_frame()
    frame = crop(frame, region)

    bg = load_image(background)

    correlation = 1 - cv2.matchTemplate(frame, bg, cv2.TM_SQDIFF_NORMED)
    _, max_, _, _ = cv2.minMaxLoc(correlation)
    selection_region = None
    if max_ >= match_threshold:
        # Find y coordinate
        rowmax = numpy.amax(correlation, axis=1)
        goodness = rowmax
        _, _, _, maxloc = cv2.minMaxLoc(goodness)
        y = maxloc[1]

        # Got the y position, now work out the horizontal extents
        line_uint8 = numpy.uint8(correlation[y, :] * 255)
        _, binary = cv2.threshold(line_uint8, 0, 255,
                                  cv2.THRESH_OTSU | cv2.THRESH_BINARY)
        binary = binary.flatten()

        nonzeros = list(
            _combine_neighbouring_extents(
                list(_zeros_to_extents(binary.nonzero()[0]))))
        if nonzeros:
            widest = max(nonzeros, key=lambda a: a[1] - a[0])
            x, right = widest
            selection_region = (stbt.Region(x,
                                            y,
                                            right=right,
                                            bottom=y + bg.shape[0]).translate(
                                                x=max(0, region.x),
                                                y=max(0, region.y)))
            if selection_region.width > 10:
                # Remove the rounded corners of the selection; after subtracting
                # the background they look like single-quotes to the OCR engine.
                selection_region = selection_region.extend(x=5, right=-5)

    if not selection_region:
        stbt.debug(
            "find_selection didn't find match (%.2f) above the threshold (%.2f)"
            % (max_, match_threshold))

    return Selection(selection_region, frame, bg)