Exemplo n.º 1
0
def test_that_results_dont_overlap(match_method):
    # This is a regression test for a bug seen in an earlier implementation of
    # `match_all`.
    frame = stbt.load_image("action-panel.png")
    all_matches = set()
    for m in stbt.match_all("action-panel-template.png", frame=frame,
                            match_parameters=mp(match_method=match_method)):
        print(m)
        assert m.region not in all_matches, "Match %s already seen:\n    %s" % (
            m, "\n    ".join(str(x) for x in all_matches))
        assert all(stbt.Region.intersect(m.region, x) is None
                   for x in all_matches)
        all_matches.add(m.region)

    assert all_matches == set([
        stbt.Region(x=135, y=433, width=222, height=40),
        stbt.Region(x=135, y=477, width=222, height=40),
        stbt.Region(x=135, y=521, width=222, height=40),
        stbt.Region(x=135, y=565, width=222, height=40),
        stbt.Region(x=135, y=609, width=222, height=40)])
Exemplo n.º 2
0
def test_match_all_with_an_image_that_matches_everywhere(match_method):
    matches = sorted(m.region for m in stbt.match_all(
        "repeating-pattern.png",
        frame=stbt.load_image("repeating-pattern-full-frame.png"),
        match_parameters=mp(match_method=match_method)))

    expected_matches = sorted([stbt.Region(x, y, width=16, height=16)
                               for x in range(0, 320, 16)
                               for y in range(0, 240, 16)])

    print(matches)
    assert matches == expected_matches
Exemplo n.º 3
0
def test_crop():
    img = stbt.load_image("action-panel.png")
    cropped = stbt.crop(img, stbt.Region(x=1045, y=672, right=1081,
                                         bottom=691))
    reference = stbt.load_image("action-panel-blue-button.png")
    assert numpy.array_equal(reference, cropped)

    # It's a view onto the same memory:
    assert cropped[0, 0, 0] == img[672, 1045, 0]
    assert img[672, 1045, 0] != 0
    cropped[0, 0, 0] = 0
    assert img[672, 1045, 0] == 0

    assert img.filename == "action-panel.png"
    assert cropped.filename == img.filename

    # Region is clipped to the frame boundaries:
    assert numpy.array_equal(
        stbt.crop(img, stbt.Region(x=1045, y=672, right=1280, bottom=720)),
        stbt.crop(img, stbt.Region(x=1045, y=672, right=1281, bottom=721)))
    assert numpy.array_equal(
        stbt.crop(img, stbt.Region(x=0, y=0, right=10, bottom=10)),
        stbt.crop(
            img,
            stbt.Region(x=float("-inf"), y=float("-inf"), right=10,
                        bottom=10)))

    # But a region entirely outside the frame is not allowed:
    with pytest.raises(TypeError):
        stbt.crop(img, None)
    with pytest.raises(ValueError):
        stbt.crop(img, stbt.Region(x=-10, y=-10, right=0, bottom=0))
Exemplo n.º 4
0
def test_match_error_message_for_too_small_frame_and_region():
    stbt.match("videotestsrc-redblue.png", frame=black(width=92, height=160))
    stbt.match("videotestsrc-redblue.png",
               frame=black(),
               region=stbt.Region(x=1188, y=560, width=92, height=160))

    with pytest.raises(ValueError) as excinfo:
        stbt.match("videotestsrc-redblue.png",
                   frame=black(width=91, height=160))
    assert (
        "Frame (160, 91, 3) must be larger than reference image (160, 92, 3)"
        in str(excinfo.value))

    with pytest.raises(ValueError) as excinfo:
        stbt.match("videotestsrc-redblue.png",
                   frame=black(width=92, height=159))
    assert (
        "Frame (159, 92, 3) must be larger than reference image (160, 92, 3)"
        in str(excinfo.value))

    with pytest.raises(ValueError) as excinfo:
        # Region seems large enough but actually it extends beyond the frame
        stbt.match("videotestsrc-redblue.png",
                   frame=black(),
                   region=stbt.Region(x=1189, y=560, width=92, height=160))
    assert (
        "Region(x=1189, y=560, right=1280, bottom=720) must be larger than "
        "reference image (160, 92, 3)" in str(excinfo.value))

    with pytest.raises(ValueError) as excinfo:
        # Region seems large enough but actually it extends beyond the frame
        stbt.match("videotestsrc-redblue.png",
                   frame=black(),
                   region=stbt.Region(x=1188, y=561, width=92, height=160))
    assert (
        "Region(x=1188, y=561, right=1280, bottom=720) must be larger than "
        "reference image (160, 92, 3)" in str(excinfo.value))
Exemplo n.º 5
0
 def message(self):
     """
     This property demonstrates an advantage of Frame Objects over
     stand-alone helper functions. We are using the position of the "info"
     icon to find this message. Because the private ``_info`` property is
     shared between this property and ``is_visible`` we don't need to
     compute it twice -- the ``FrameObject`` base class will remember the
     value from the first time it was computed.
     """
     right_of_info = stbt.Region(x=self._info.region.right,
                                 y=self._info.region.y,
                                 width=390,
                                 height=self._info.region.height)
     return stbt.ocr(region=right_of_info, frame=self._frame) \
                .replace('\n', ' ')
Exemplo n.º 6
0
def test_detect_motion_region_and_mask():
    def dm(**kwargs):
        return next(stbt.detect_motion(frames=wipe(), **kwargs))

    r = stbt.Region(0, 0, right=640, bottom=1280)

    # Just check no exceptions
    dm()
    dm(mask="mask-out-left-half-720p.png")
    dm(mask=numpy.zeros((720, 1280), dtype=numpy.uint8))
    dm(region=r)
    dm(region=r, mask=numpy.zeros((720, 640), dtype=numpy.uint8))

    with pytest.raises(ValueError):
        dm(region=r, mask="mask-out-left-half-720p.png")
Exemplo n.º 7
0
def test_merge_regions_performance(n):
    random.seed(1)
    regions = []
    for _ in range(n):
        x = random.randint(0, 1280)
        y = random.randint(0, 720)
        right = random.randint(0, 1280)
        bottom = random.randint(0, 720)
        x, w = min(x, right), max(x, right) - min(x, right) + 1
        y, h = min(y, bottom), max(y, bottom) - min(y, bottom) + 1
        regions.append(stbt.Region(x, y, w, h))

    times = timeit.repeat(lambda: _merge_regions(regions[:]),
                          number=1, repeat=10)
    print(times)
    print(min(times))
    assert min(times) < (0.001 * n / 20)
Exemplo n.º 8
0
def test_that_slicing_a_Frame_is_still_a_Frame():
    f = stbt.Frame(numpy.zeros((720, 1280, 3), dtype=numpy.uint8), time=1234)

    f1 = f[10:20, 10:, 0]
    assert isinstance(f1, stbt.Frame)
    assert f1.time == 1234

    f2 = stbt.crop(f, stbt.Region(10, 10, 20, 20))
    assert isinstance(f2, stbt.Frame)
    assert f2.time == 1234

    f3 = f.copy()
    assert isinstance(f3, stbt.Frame)
    assert f3.time == 1234
    assert (f.__array_interface__["data"][0] !=
            f3.__array_interface__["data"][0])

    f4 = stbt.Frame(f)
    assert f4.time == 1234
Exemplo n.º 9
0
def test_is_screen_black_debug():
    # So that the output directory name doesn't depend on how many tests
    # were run before this one.
    ImageLogger._frame_number = itertools.count(1)  # pylint:disable=protected-access

    f = stbt.load_image("videotestsrc-full-frame.png")

    with scoped_curdir(), scoped_debug_level(2):

        stbt.is_screen_black(f)
        stbt.is_screen_black(f, mask="videotestsrc-mask-non-black.png")
        stbt.is_screen_black(f, mask="videotestsrc-mask-no-video.png")
        stbt.is_screen_black(f, region=stbt.Region(0, 0, 160, 120))

        files = subprocess.check_output("find stbt-debug | sort", shell=True) \
                          .decode("utf-8")
        assert files == dedent("""\
            stbt-debug
            stbt-debug/00001
            stbt-debug/00001/grey.png
            stbt-debug/00001/index.html
            stbt-debug/00001/non_black.png
            stbt-debug/00001/source.png
            stbt-debug/00002
            stbt-debug/00002/grey.png
            stbt-debug/00002/index.html
            stbt-debug/00002/mask.png
            stbt-debug/00002/non_black.png
            stbt-debug/00002/source.png
            stbt-debug/00003
            stbt-debug/00003/grey.png
            stbt-debug/00003/index.html
            stbt-debug/00003/mask.png
            stbt-debug/00003/non_black.png
            stbt-debug/00003/source.png
            stbt-debug/00004
            stbt-debug/00004/grey.png
            stbt-debug/00004/index.html
            stbt-debug/00004/non_black.png
            stbt-debug/00004/source.png
            """)

        assert_expected("stbt-debug-expected-output/is_screen_black")
Exemplo n.º 10
0
def _test_that_cache_speeds_up_ocr():
    frame = load_image('red-black.png')

    def ocr():
        return stbt.ocr(frame=frame)

    # pylint:disable=protected-access
    _cache = imgproc_cache._cache
    imgproc_cache._cache = None
    uncached_result = ocr()
    uncached_time = min(timeit.repeat(ocr, repeat=10, number=1))
    imgproc_cache._cache = _cache

    cached_result = ocr()  # prime the cache
    cached_time = min(timeit.repeat(ocr, repeat=10, number=1))

    print("ocr with cache: %s" % (cached_time, ))
    print("ocr without cache: %s" % (uncached_time, ))
    assert uncached_time > (cached_time * 10)
    assert type(cached_result) == type(uncached_result)  # pylint:disable=unidiomatic-typecheck
    assert cached_result == uncached_result

    r = stbt.Region(x=0, y=32, right=91, bottom=59)
    frame2 = load_image("red-black-2.png")

    def cached_ocr1():
        return stbt.ocr(frame=frame, region=r)

    def cached_ocr2():
        return stbt.ocr(frame=frame2, region=r)

    cached_ocr1()  # prime the cache
    time1 = timeit.timeit(cached_ocr1, number=1)
    time2 = timeit.timeit(cached_ocr2, number=1)

    print("ocr with cache (frame 1): %s" % (time1, ))
    print("ocr with cache (frame 2): %s" % (time2, ))
    assert time2 < (time1 * 10)
    assert cached_ocr1() == cached_ocr2()
Exemplo n.º 11
0
def test_region_replace():
    r = stbt.Region(x=10, y=20, width=20, height=30)

    def t(kwargs, expected):
        assert r.replace(**kwargs) == expected

    def e(kwargs):
        with pytest.raises(ValueError):
            r.replace(**kwargs)

    # No change
    yield t, dict(x=10), r
    yield t, dict(x=10, width=20), r
    yield t, dict(x=10, right=30), r

    # Not allowed
    yield e, dict(x=1, width=2, right=3)
    yield e, dict(y=1, height=2, bottom=3)

    # Allowed  # pylint:disable=line-too-long
    yield t, dict(x=11), stbt.Region(x=11, y=r.y, width=19, height=r.height)
    yield t, dict(width=19), stbt.Region(x=10,
                                         y=r.y,
                                         width=19,
                                         height=r.height)
    yield t, dict(right=29), stbt.Region(x=10,
                                         y=r.y,
                                         width=19,
                                         height=r.height)
    yield t, dict(x=11, width=20), stbt.Region(x=11,
                                               y=r.y,
                                               width=20,
                                               height=r.height)
    yield t, dict(x=11, right=21), stbt.Region(x=11,
                                               y=r.y,
                                               width=10,
                                               height=r.height)
    yield t, dict(x=11, right=21, y=0, height=5), stbt.Region(x=11,
                                                              y=0,
                                                              width=10,
                                                              height=5)
Exemplo n.º 12
0
def test_region_translate():
    with pytest.raises(TypeError):
        # Both region and y provided
        stbt.Region(2, 3, 2, 1).translate(stbt.Region(0, 0, 1, 1), 5)
Exemplo n.º 13
0

def requires_tesseract(func):
    """Decorator for tests that require Tesseract to be installed."""
    try:
        _tesseract_version()
    except:
        raise SkipTest("tesseract isn't installed")
    return func


@requires_tesseract
@pytest.mark.parametrize("image, expected_text, region, mode", [
    # pylint: disable=line-too-long
    ("Connection-status--white-on-dark-blue.png", "Connection status: Connected", stbt.Region.ALL, None),
    ("Connection-status--white-on-dark-blue.png", "Connected", stbt.Region(x=210, y=0, width=120, height=40), None),
    # ("Connection-status--white-on-dark-blue.png", "", None, None),  # uncomment when region=None doesn't raise -- see #433
    ("programme--white-on-black.png", "programme", stbt.Region.ALL, None),
    ("UJJM--white-text-on-grey-boxes.png", "", stbt.Region.ALL, None),
    ("UJJM--white-text-on-grey-boxes.png", "UJJM", stbt.Region.ALL, stbt.OcrMode.SINGLE_LINE),
])
def test_ocr_on_static_images(image, expected_text, region, mode):
    kwargs = {"region": region}
    if mode is not None:
        kwargs["mode"] = mode
    text = stbt.ocr(load_image("ocr/" + image), **kwargs)
    assert text == expected_text

    # Don't leak python future newtypes
    assert type(text).__name__ in ["unicode", "str"]
Exemplo n.º 14
0

@pytest.mark.parametrize(
    "frame,mask,threshold,region,expected",
    [
        # pylint:disable=line-too-long
        ("black-full-frame.png", None, None, stbt.Region.ALL, True),
        ("videotestsrc-full-frame.png", None, None, stbt.Region.ALL, False),
        ("videotestsrc-full-frame.png", "videotestsrc-mask-non-black.png",
         None, stbt.Region.ALL, True),
        ("videotestsrc-full-frame.png", "videotestsrc-mask-no-video.png", None,
         stbt.Region.ALL, False),
        ("videotestsrc-full-frame.png", "videotestsrc-mask-no-video.png", None,
         stbt.Region.ALL, False),
        ("videotestsrc-full-frame.png", None, 20,
         stbt.Region(x=160, y=180, right=240, bottom=240), True),
        # Threshold bounds for almost-black frame:
        ("almost-black.png", None, 3, stbt.Region.ALL, True),
        ("almost-black.png", None, 2, stbt.Region.ALL, False),
    ])
def test_is_screen_black(frame, mask, threshold, region, expected):
    frame = stbt.load_image(frame)
    assert expected == bool(
        stbt.is_screen_black(frame, mask, threshold, region))


def test_is_screen_black_result():
    frame = stbt.load_image("almost-black.png")
    result = stbt.is_screen_black(frame)
    assert result
    assert numpy.all(result.frame == frame)
Exemplo n.º 15
0
def test_ocr_debug():
    # So that the output directory name doesn't depend on how many tests
    # were run before this one.
    ImageLogger._frame_number = itertools.count(1)  # pylint:disable=protected-access

    f = stbt.load_image("action-panel.png")
    r = stbt.Region(0, 370, right=1280, bottom=410)
    c = (235, 235, 235)
    nonoverlapping = stbt.Region(2000, 2000, width=10, height=10)

    with scoped_curdir(), scoped_debug_level(2):

        stbt.ocr(f)
        stbt.ocr(f, region=r)
        stbt.ocr(f, region=r, text_color=c)
        stbt.ocr(f, region=nonoverlapping)

        stbt.match_text("Summary", f)  # no match
        stbt.match_text("Summary", f, region=r)  # no match
        stbt.match_text("Summary", f, region=r, text_color=c)
        stbt.match_text("Summary", f, region=nonoverlapping)

        files = subprocess.check_output("find stbt-debug | sort", shell=True) \
                          .decode("utf-8")
        assert files == dedent("""\
            stbt-debug
            stbt-debug/00001
            stbt-debug/00001/index.html
            stbt-debug/00001/source.png
            stbt-debug/00001/tessinput.png
            stbt-debug/00001/upsampled.png
            stbt-debug/00002
            stbt-debug/00002/index.html
            stbt-debug/00002/source.png
            stbt-debug/00002/tessinput.png
            stbt-debug/00002/upsampled.png
            stbt-debug/00003
            stbt-debug/00003/index.html
            stbt-debug/00003/source.png
            stbt-debug/00003/tessinput.png
            stbt-debug/00003/text_color_difference.png
            stbt-debug/00003/text_color_threshold.png
            stbt-debug/00003/upsampled.png
            stbt-debug/00004
            stbt-debug/00004/index.html
            stbt-debug/00004/source.png
            stbt-debug/00005
            stbt-debug/00005/index.html
            stbt-debug/00005/source.png
            stbt-debug/00005/tessinput.png
            stbt-debug/00005/upsampled.png
            stbt-debug/00006
            stbt-debug/00006/index.html
            stbt-debug/00006/source.png
            stbt-debug/00006/tessinput.png
            stbt-debug/00006/upsampled.png
            stbt-debug/00007
            stbt-debug/00007/index.html
            stbt-debug/00007/source.png
            stbt-debug/00007/tessinput.png
            stbt-debug/00007/text_color_difference.png
            stbt-debug/00007/text_color_threshold.png
            stbt-debug/00007/upsampled.png
            stbt-debug/00008
            stbt-debug/00008/index.html
            stbt-debug/00008/source.png
            """)
Exemplo n.º 16
0
def test_composing_complex_keyboards():
    """The YouTube keyboard on Roku looks like this::

        A  B  C  D  E  F  G
        H  I  J  K  L  M  N
        O  P  Q  R  S  T  U
        V  W  X  Y  Z  -  '
         SPACE  CLEAR  SEARCH

    The first 4 rows behave normally within themselves. The bottom row behaves
    normally within itself. But navigating to or from the bottom row is a bit
    irregular: No matter what column you're in, when you press KEY_DOWN you
    always land on SPACE. Then when you press KEY_UP, you go back to the column
    you were last on -- even if you had pressed KEY_RIGHT/KEY_LEFT to move
    within the bottom row. It's almost like they're two separate state
    machines, and we can model them as such, with a few explicit connections
    between the two.
    """
    letters = stbt.Grid(stbt.Region(x=540, y=100, right=840, bottom=280),
                        data=["ABCDEFG", "HIJKLMN", "OPQRSTU", "VWXYZ-'"])
    space_row = stbt.Grid(stbt.Region(x=540, y=280, right=840, bottom=330),
                          data=[[" ", "CLEAR", "SEARCH"]])

    # Technique #0: Write the entire edgelist manually (as per previous tests)
    K0 = stbt.Keyboard(GRAPH)

    # Technique #1: Manipulate the graph (manually or programmatically) directly
    G1 = nx.compose(stbt.grid_to_navigation_graph(letters),
                    stbt.grid_to_navigation_graph(space_row))
    # Pressing down from the bottom row always goes to SPACE:
    for k in letters.data[-1]:
        G1.add_edge(k, " ", key="KEY_DOWN")
    # Pressing back up from the space/clear/search row can go to any column
    # in the bottom row:
    for k in space_row.data[0]:
        for j in letters.data[-1]:
            G1.add_edge(k, j, key="KEY_UP")
    K1 = stbt.Keyboard(G1)

    assert sorted(K0.G.edges(data=True)) == sorted(K1.G.edges(data=True))

    # Technique #2: Use manually-written edgelist only for the irregular edges
    # Note that Keyboard.__init__ will normalise "SPACE" -> " " so it doesn't
    # matter if the 3 different graphs have different representations for
    # "SPACE".
    connections = stbt.Keyboard.parse_edgelist("""
        V SPACE KEY_DOWN
        W SPACE KEY_DOWN
        X SPACE KEY_DOWN
        Y SPACE KEY_DOWN
        Z SPACE KEY_DOWN
        - SPACE KEY_DOWN
        ' SPACE KEY_DOWN
        SPACE V KEY_UP
        SPACE W KEY_UP
        SPACE X KEY_UP
        SPACE Y KEY_UP
        SPACE Z KEY_UP
        SPACE - KEY_UP
        SPACE ' KEY_UP
        CLEAR V KEY_UP
        CLEAR W KEY_UP
        CLEAR X KEY_UP
        CLEAR Y KEY_UP
        CLEAR Z KEY_UP
        CLEAR - KEY_UP
        CLEAR ' KEY_UP
        SEARCH V KEY_UP
        SEARCH W KEY_UP
        SEARCH X KEY_UP
        SEARCH Y KEY_UP
        SEARCH Z KEY_UP
        SEARCH - KEY_UP
        SEARCH ' KEY_UP
    """)
    G2 = nx.compose_all([
        stbt.grid_to_navigation_graph(letters),
        stbt.grid_to_navigation_graph(space_row), connections
    ])
    K2 = stbt.Keyboard(G2)

    assert sorted(K0.G.edges(data=True)) == sorted(K2.G.edges(data=True))
Exemplo n.º 17
0
def test_motion_debug():
    # So that the output directory name doesn't depend on how many tests
    # were run before this one.
    ImageLogger._frame_number = itertools.count(1)  # pylint:disable=protected-access

    def fake_frames():
        for i, f in enumerate(
            ["box-00001.png", "box-00002.png", "box-00003.png"]):
            yield stbt.Frame(stbt.load_image(f), time=i)

    with scoped_curdir(), scoped_debug_level(2):

        for _ in stbt.detect_motion(frames=fake_frames()):
            pass
        for _ in stbt.detect_motion(frames=fake_frames(),
                                    mask="box-00000.png"):
            pass
        for _ in stbt.detect_motion(frames=fake_frames(),
                                    region=stbt.Region(0, 0, 320, 400)):
            pass

        files = subprocess.check_output("find stbt-debug | sort", shell=True) \
                          .decode("utf-8")
        assert files == dedent("""\
            stbt-debug
            stbt-debug/00001
            stbt-debug/00001/absdiff.png
            stbt-debug/00001/absdiff_threshold_erode.png
            stbt-debug/00001/absdiff_threshold.png
            stbt-debug/00001/gray.png
            stbt-debug/00001/index.html
            stbt-debug/00001/previous_frame_gray.png
            stbt-debug/00001/source.png
            stbt-debug/00002
            stbt-debug/00002/absdiff.png
            stbt-debug/00002/absdiff_threshold_erode.png
            stbt-debug/00002/absdiff_threshold.png
            stbt-debug/00002/gray.png
            stbt-debug/00002/index.html
            stbt-debug/00002/previous_frame_gray.png
            stbt-debug/00002/source.png
            stbt-debug/00003
            stbt-debug/00003/absdiff_masked.png
            stbt-debug/00003/absdiff.png
            stbt-debug/00003/absdiff_threshold_erode.png
            stbt-debug/00003/absdiff_threshold.png
            stbt-debug/00003/gray.png
            stbt-debug/00003/index.html
            stbt-debug/00003/mask.png
            stbt-debug/00003/previous_frame_gray.png
            stbt-debug/00003/source.png
            stbt-debug/00004
            stbt-debug/00004/absdiff_masked.png
            stbt-debug/00004/absdiff.png
            stbt-debug/00004/absdiff_threshold_erode.png
            stbt-debug/00004/absdiff_threshold.png
            stbt-debug/00004/gray.png
            stbt-debug/00004/index.html
            stbt-debug/00004/mask.png
            stbt-debug/00004/previous_frame_gray.png
            stbt-debug/00004/source.png
            stbt-debug/00005
            stbt-debug/00005/absdiff.png
            stbt-debug/00005/absdiff_threshold_erode.png
            stbt-debug/00005/absdiff_threshold.png
            stbt-debug/00005/gray.png
            stbt-debug/00005/index.html
            stbt-debug/00005/previous_frame_gray.png
            stbt-debug/00005/source.png
            stbt-debug/00006
            stbt-debug/00006/absdiff.png
            stbt-debug/00006/absdiff_threshold_erode.png
            stbt-debug/00006/absdiff_threshold.png
            stbt-debug/00006/gray.png
            stbt-debug/00006/index.html
            stbt-debug/00006/previous_frame_gray.png
            stbt-debug/00006/source.png
        """)

        assert_expected("stbt-debug-expected-output/motion")
Exemplo n.º 18
0
    expected = stbt.Region(5, 5, right=20, bottom=10)
    assert expected == stbt.Region.intersect(r1, r2)
    with pytest.raises(AttributeError):
        r1.intersect(r2)  # pylint:disable=no-member


def test_region_bounding_box():
    r1 = stbt.Region(0, 0, right=20, bottom=10)
    r2 = stbt.Region(5, 5, right=25, bottom=15)
    expected = stbt.Region(0, 0, right=25, bottom=15)
    assert expected == stbt.Region.bounding_box(r1, r2)
    with pytest.raises(AttributeError):
        r1.bounding_box(r2)  # pylint:disable=no-member


r = stbt.Region(x=10, y=20, width=20, height=30)


@pytest.mark.parametrize(
    "kwargs,expected",
    [
        # No change
        (dict(x=10), r),
        (dict(x=10, width=20), r),
        (dict(x=10, right=30), r),

        # Allowed  # pylint:disable=line-too-long
        (dict(x=11), stbt.Region(x=11, y=r.y, width=19, height=r.height)),
        (dict(width=19), stbt.Region(x=10, y=r.y, width=19, height=r.height)),
        (dict(right=29), stbt.Region(x=10, y=r.y, width=19, height=r.height)),
        (dict(x=11,
Exemplo n.º 19
0
    try:
        _tesseract_version()
    except:
        raise SkipTest("tesseract isn't installed")
    return func


@requires_tesseract
@pytest.mark.parametrize(
    "image, expected_text, region, mode",
    [
        # pylint: disable=line-too-long
        ("Connection-status--white-on-dark-blue.png",
         "Connection status: Connected", stbt.Region.ALL, None),
        ("Connection-status--white-on-dark-blue.png", "Connected",
         stbt.Region(x=210, y=0, width=120, height=40), None),
        ("programme--white-on-black.png", "programme", stbt.Region.ALL, None),
        ("UJJM--white-text-on-grey-boxes.png", "", stbt.Region.ALL, None),
        ("UJJM--white-text-on-grey-boxes.png", "UJJM", stbt.Region.ALL,
         stbt.OcrMode.SINGLE_LINE),
    ])
def test_ocr_on_static_images(image, expected_text, region, mode):
    kwargs = {"region": region}
    if mode is not None:
        kwargs["mode"] = mode
    text = stbt.ocr(load_image("ocr/" + image), **kwargs)
    assert text == expected_text


@requires_tesseract
def test_ocr_doesnt_leak_python_future_newtypes():
Exemplo n.º 20
0

@pytest.mark.parametrize("match_method", [
    stbt.MatchMethod.SQDIFF,
    stbt.MatchMethod.SQDIFF_NORMED,
])
def test_that_if_image_doesnt_match_match_all_returns_empty_array(
        match_method):
    assert [] == list(
        stbt.match_all('button.png',
                       frame=stbt.load_image('black-full-frame.png'),
                       match_parameters=mp(match_method=match_method)))


plain_buttons = [
    stbt.Region(_x, _y, width=135, height=44)
    for _x, _y in [(28, 1), (163, 1), (177, 75), (177, 119), (177,
                                                              163), (298, 1)]
]
labelled_buttons = [
    stbt.Region(_x, _y, width=135, height=44) for _x, _y in [(1, 65), (6, 137)]
]
overlapping_button = stbt.Region(123, 223, width=135, height=44)
overlapped_button = stbt.Region(3, 223, width=135, height=44)


@pytest.mark.parametrize("match_method", [
    stbt.MatchMethod.SQDIFF,
    stbt.MatchMethod.SQDIFF_NORMED,
    stbt.MatchMethod.CCORR_NORMED,
    stbt.MatchMethod.CCOEFF_NORMED,
Exemplo n.º 21
0
    expected = stbt.Region(5, 5, right=20, bottom=10)
    assert expected == stbt.Region.intersect(r1, r2)
    with pytest.raises(AttributeError):
        r1.intersect(r2)  # pylint:disable=no-member


def test_region_bounding_box():
    r1 = stbt.Region(0, 0, right=20, bottom=10)
    r2 = stbt.Region(5, 5, right=25, bottom=15)
    expected = stbt.Region(0, 0, right=25, bottom=15)
    assert expected == stbt.Region.bounding_box(r1, r2)
    with pytest.raises(AttributeError):
        r1.bounding_box(r2)  # pylint:disable=no-member


r = stbt.Region(x=10, y=20, width=20, height=30)


@pytest.mark.parametrize("kwargs,expected", [
    # No change
    (dict(x=10), r),
    (dict(x=10, width=20), r),
    (dict(x=10, right=30), r),

    # Allowed  # pylint:disable=line-too-long
    (dict(x=11), stbt.Region(x=11, y=r.y, width=19, height=r.height)),
    (dict(width=19), stbt.Region(x=10, y=r.y, width=19, height=r.height)),
    (dict(right=29), stbt.Region(x=10, y=r.y, width=19, height=r.height)),
    (dict(x=11, width=20), stbt.Region(x=11, y=r.y, width=20, height=r.height)),
    (dict(x=11, right=21), stbt.Region(x=11, y=r.y, width=10, height=r.height)),
    (dict(x=11, right=21, y=0, height=5), stbt.Region(x=11, y=0, width=10, height=5)),
Exemplo n.º 22
0
def test_that_keyboard_catches_errors_at_definition_time():
    kb = stbt.Keyboard()

    # Can't add the same key twice:
    kb.add_key("a")
    with pytest.raises(ValueError) as excinfo:
        kb.add_key("a")
    assert_repr_equal(
        "Key already exists: Key(name='a', text='a', region=None, mode=None)",
        str(excinfo.value))

    # Can't add transition to key that doesn't exist:
    with pytest.raises(ValueError) as excinfo:
        kb.add_transition("a", "b", "KEY_RIGHT")
    assert_repr_equal("Query 'b' doesn't match any key in the keyboard",
                      str(excinfo.value))

    # ...but add_edgelist creates keys as needed:
    kb.add_edgelist("a b KEY_RIGHT")

    # All keys must have modes or none of them can
    kb.add_key(" ")
    with pytest.raises(ValueError) as excinfo:
        kb.add_key(" ", mode="uppercase")
    assert_repr_equal(
        "Key ...'name': ' '...'mode': 'uppercase'... specifies 'mode', but none of the other keys in the keyboard do",  # pylint:disable=line-too-long
        str(excinfo.value))

    # All keys must have regions or none of them can
    with pytest.raises(ValueError) as excinfo:
        kb.add_grid(stbt.Grid(
            region=stbt.Region(x=0, y=0, right=200, bottom=100),
            data=[["a", "b", "c", "d"]]))
    assert_repr_equal(
        "Key ...'a'... specifies 'region', but none of the other keys in the keyboard do",  # pylint:disable=line-too-long
        str(excinfo.value))

    # Can't add grid with no data:
    with pytest.raises(ValueError) as excinfo:
        kb.add_grid(stbt.Grid(
            region=stbt.Region(x=0, y=0, right=200, bottom=100),
            cols=6, rows=6))
    assert_repr_equal("Grid cell [0,0] doesn't have any data",
                      str(excinfo.value))

    # Now a keyboard with modes: #############################################
    kb = stbt.Keyboard()
    kb.add_key("a", mode="lowercase")
    kb.add_key("A", mode="uppercase")
    kb.add_key(" ", mode="lowercase")

    # All keys must have modes or none of them can
    with pytest.raises(ValueError) as excinfo:
        kb.add_key(" ")
    assert_repr_equal(
        "Key already exists: Key(name=' ', text=' ', region=None, mode='lowercase')",  # pylint:disable=line-too-long
        str(excinfo.value))
    with pytest.raises(ValueError) as excinfo:
        kb.add_key("b")
    assert_repr_equal(
        "Key ...'name': 'b'... doesn't specify 'mode', but all the other keys in the keyboard do",  # pylint:disable=line-too-long
        str(excinfo.value))

    # add_edgelist is happy as long as it can uniquely identify existing keys:
    kb.add_edgelist("a SPACE KEY_DOWN")

    # ...but if it's ambiguous, it's an error:
    kb.add_key(" ", mode="uppercase")
    with pytest.raises(ValueError) as excinfo:
        kb.add_edgelist("a SPACE KEY_DOWN")
    assert_repr_equal(
        "Ambiguous key {'name': ' '}: Could mean Key(name=' ', text=' ', region=None, mode='lowercase') or Key(name=' ', text=' ', region=None, mode='uppercase')",  # pylint:disable=line-too-long
        str(excinfo.value))

    # ...so we need to specify the mode explicitly:
    kb.add_edgelist("a SPACE KEY_DOWN", mode="lowercase")
Exemplo n.º 23
0
    print(transition)
    assert not transition
    assert transition.status == stbt.TransitionStatus.STABLE_TIMEOUT

    transition = stbt.press_and_wait("ball", stable_secs=0,
                                     _dut=FakeDeviceUnderTest())
    print(transition)
    assert transition
    assert transition.status == stbt.TransitionStatus.COMPLETE


@pytest.mark.parametrize("mask,region,expected", [
    (None, stbt.Region.ALL, stbt.TransitionStatus.STABLE_TIMEOUT),
    ("mask-out-left-half-720p.png", stbt.Region.ALL,
     stbt.TransitionStatus.START_TIMEOUT),
    (None, stbt.Region(x=640, y=0, right=1280, bottom=720),
     stbt.TransitionStatus.START_TIMEOUT),
    (None, stbt.Region(x=0, y=0, right=1280, bottom=360),
     stbt.TransitionStatus.STABLE_TIMEOUT),
])
def test_press_and_wait_with_mask_or_region(mask, region, expected):
    transition = stbt.press_and_wait(
        "ball", mask=mask, region=region, timeout_secs=0.2, stable_secs=0.1,
        _dut=FakeDeviceUnderTest())
    print(transition)
    assert transition.status == expected


def test_wait_for_transition_to_end():
    _stbt = FakeDeviceUnderTest()
Exemplo n.º 24
0
    def refresh(self, frame=None, **kwargs):
        page = SearchPage(self.dut, self.kb)
        logging.debug("SearchPage.refresh: Now on %r", page.selection)
        return page

    def enter_text(self, text):
        return self.kb.enter_text(text, page=self)

    def navigate_to(self, target, verify_every_keypress=False):
        return self.kb.navigate_to(target, page=self,
                                   verify_every_keypress=verify_every_keypress)


kb1 = stbt.Keyboard()  # Full model with modes, defined using Grids
MODES_GRID = stbt.Grid(
    region=stbt.Region(x=125, y=95, right=430, bottom=140),
    data=[["lowercase", "uppercase", "symbols"]])
MIDDLE_REGION = stbt.Region(x=125, y=140, right=430, bottom=445)
MIDDLE_GRIDS = {
    "lowercase": stbt.Grid(region=MIDDLE_REGION,
                           data=[
                               "abcdef",
                               "ghijkl",
                               "mnopqr",
                               "stuvwx",
                               "yz1234",
                               "567890"]),
    "uppercase": stbt.Grid(region=MIDDLE_REGION,
                           data=[
                               "ABCDEF",
                               "GHIJKL",
Exemplo n.º 25
0
def test_that_match_converts_greyscale_reference_image(filename):
    stbt.match(filename, frame=black())  # Doesn't raise
    stbt.match(stbt.load_image(filename), frame=black())


@pytest.mark.parametrize("match_method", [
    stbt.MatchMethod.SQDIFF,
    stbt.MatchMethod.SQDIFF_NORMED,
])
def test_that_if_image_doesnt_match_match_all_returns_empty_array(match_method):
    assert [] == list(stbt.match_all(
        'button.png', frame=stbt.load_image('black-full-frame.png'),
        match_parameters=mp(match_method=match_method)))


plain_buttons = [stbt.Region(_x, _y, width=135, height=44) for _x, _y in [
    (28, 1), (163, 1), (177, 75), (177, 119), (177, 163), (298, 1)]]
labelled_buttons = [stbt.Region(_x, _y, width=135, height=44) for _x, _y in [
    (1, 65), (6, 137)]]
overlapping_button = stbt.Region(123, 223, width=135, height=44)
overlapped_button = stbt.Region(3, 223, width=135, height=44)


@pytest.mark.parametrize("match_method", [
    stbt.MatchMethod.SQDIFF,
    stbt.MatchMethod.SQDIFF_NORMED,
    stbt.MatchMethod.CCORR_NORMED,
    stbt.MatchMethod.CCOEFF_NORMED,
])
def test_that_match_all_finds_all_matches(match_method):
    matches = list(m.region for m in stbt.match_all(