def test_nearby_clipping(self): screen = AutoPyController() screen_width = screen.width screen_height = screen.height # clip upper side region = Region(200, 100, 20, 10).nearby(rrange=150) self.assertEqual(50, region.x) self.assertEqual(0, region.y) self.assertEqual(320, region.width) self.assertEqual(260, region.height) # clip lower side region = Region(200, screen_height - 30, 20, 10).nearby(rrange=50) self.assertEqual(150, region.x) self.assertEqual(screen_height - 30 - 50, region.y) self.assertEqual(120, region.width) self.assertEqual(80, region.height) # clip left side region = Region(20, 100, 30, 10).nearby(rrange=50) self.assertEqual(0, region.x) self.assertEqual(50, region.y) self.assertEqual(100, region.width) self.assertEqual(110, region.height) # clip right side region = Region(screen_width - 30, 100, 20, 10).nearby(rrange=50) self.assertEqual(screen_width - 30 - 50, region.x) self.assertEqual(50, region.y) self.assertEqual(80, region.width) self.assertEqual(110, region.height)
def test_left(self): region = Region(200, 100, 20, 10).left(50) self.assertEqual(150, region.x) self.assertEqual(100, region.y) self.assertEqual(70, region.width) self.assertEqual(10, region.height) region = Region(200, 100, 20, 10).left(80000) self.assertEqual(0, region.x) self.assertEqual(100, region.y) self.assertEqual(220, region.width) self.assertEqual(10, region.height) # extend to full screen above region = Region(200, 100, 20, 10).left() self.assertEqual(0, region.x) self.assertEqual(100, region.y) self.assertEqual(220, region.width) self.assertEqual(10, region.height)
def test_above(self): region = Region(200, 100, 20, 10).above(50) self.assertEqual(200, region.x) self.assertEqual(50, region.y) self.assertEqual(20, region.width) self.assertEqual(60, region.height) region = Region(200, 100, 20, 10).above(80000) self.assertEqual(200, region.x) self.assertEqual(0, region.y) self.assertEqual(20, region.width) self.assertEqual(110, region.height) # extend to full screen above region = Region(200, 100, 20, 10).above() self.assertEqual(200, region.x) self.assertEqual(0, region.y) self.assertEqual(20, region.width) self.assertEqual(110, region.height)
def setUp(self): # gui test scripts self.script_app = os.path.join(common_test.unittest_dir, 'qt5_application.py') self.child_app = None # prefixed controls # NOTE: provide and use only fixed locations to avoid CV backend dependencies self.click_control = Location(75, 25) self.double_click_control = Location(185, 20) self.context_menu_control = Location(315, 20) self.context_menu_close_control = Location(355, 35) self.mouse_down_control = Location(435, 95) self.mouse_up_control = Location(435, 135) self.textedit_control = Location(35, 135) self.textedit_quit_control = Location(65, 60) self.textedit_any_control = Location(65, 95) self.drag_control = Location(435, 25) self.drop_control = Location(435, 65) self.region = Region()
def test_screen_clipping(self): screen = AutoPyController() screen_width = screen.width screen_height = screen.height region = Region(0, 0, 80000, 40000) self.assertEqual(screen_width, region.width) self.assertEqual(screen_height, region.height) region = Region(80000, 40000, 300, 200) self.assertEqual(screen_width - 1, region.x) self.assertEqual(screen_height - 1, region.y) self.assertEqual(1, region.width) self.assertEqual(1, region.height) region = Region(200, 100, screen_width * 2, screen_height * 2) self.assertEqual(200, region.x) self.assertEqual(100, region.y) self.assertEqual(screen_width - region.x, region.width) self.assertEqual(screen_height - region.y, region.height)
def test_right(self): screen_width = AutoPyController().width region = Region(200, 100, 20, 10).right(50) self.assertEqual(200, region.x) self.assertEqual(100, region.y) self.assertEqual(70, region.width) self.assertEqual(10, region.height) region = Region(200, 100, 20, 10).right(80000) self.assertEqual(200, region.x) self.assertEqual(100, region.y) self.assertEqual(screen_width - region.x, region.width) self.assertEqual(10, region.height) # extend to full screen above region = Region(200, 100, 20, 10).right() self.assertEqual(200, region.x) self.assertEqual(100, region.y) self.assertEqual(screen_width - region.x, region.width) self.assertEqual(10, region.height)
def test_below(self): screen_height = AutoPyController().height region = Region(200, 100, 20, 10).below(50) self.assertEqual(200, region.x) self.assertEqual(100, region.y) self.assertEqual(20, region.width) self.assertEqual(60, region.height) region = Region(200, 100, 20, 10).below(80000) self.assertEqual(200, region.x) self.assertEqual(100, region.y) self.assertEqual(20, region.width) self.assertEqual(screen_height - region.y, region.height) # extend to full screen below region = Region(200, 100, 20, 10).below() self.assertEqual(200, region.x) self.assertEqual(100, region.y) self.assertEqual(20, region.width) self.assertEqual(screen_height - region.y, region.height)
def test_empty_screen_clipping(self): screen = Controller() screen_width = screen.width screen_height = screen.height self.assertEqual(screen_width, 0) self.assertEqual(screen_height, 0) region = Region(0, 0, 80000, 40000, dc=screen) self.assertEqual(region.width, 80000) self.assertEqual(region.height, 40000) region = Region(80000, 40000, 300, 200, dc=screen) self.assertEqual(region.x, 80000) self.assertEqual(region.y, 40000) self.assertEqual(region.width, 300) self.assertEqual(region.height, 200) region = Region(-300, -200, 300, 200, dc=screen) self.assertEqual(region.x, -300) self.assertEqual(region.y, -200) self.assertEqual(region.width, 300) self.assertEqual(region.height, 200)
def test_nearby(self): screen = AutoPyController() screen_width = screen.width screen_height = screen.height # defaults to 50 pixels region = Region(200, 100, 20, 10).nearby() self.assertEqual(150, region.x) self.assertEqual(50, region.y) self.assertEqual(120, region.width) self.assertEqual(110, region.height) region = Region(200, 100, 20, 10).nearby(rrange=80000) self.assertEqual(0, region.x) self.assertEqual(0, region.y) self.assertEqual(screen_width, region.width) self.assertEqual(screen_height, region.height) region = Region(200, 100, 20, 10).nearby(rrange=0) self.assertEqual(200, region.x) self.assertEqual(100, region.y) self.assertEqual(20, region.width) self.assertEqual(10, region.height)
def test_initialize(self): screen_width = AutoPyController().width screen_height = AutoPyController().height self.assertEqual(0, self.region.x) self.assertEqual(0, self.region.y) self.assertEqual(screen_width, self.region.width) self.assertEqual(screen_height, self.region.height) region = Region(10, 20, 300, 200) self.assertEqual(10, region.x) self.assertEqual(20, region.y) self.assertEqual(300, region.width) self.assertEqual(200, region.height)
def test_sample(self): self.show_image('all_shapes') # autopy matching does not support similarity shapes = Region(cv=AutoPyFinder()) similarity = shapes.sample(Image('shape_blue_circle')) self.assertEqual(similarity, 0.0) # initialize template matching region to support similarity shapes = Region(cv=TemplateFinder()) similarity = shapes.sample(Image('shape_blue_circle')) self.assertAlmostEqual(similarity, 0.999999, delta=0.001) self.close_windows()
def test_capture(self): for display in self.backends: screen_width = display.width screen_height = display.height # Fullscreen capture captured = display.capture_screen() self.assertEqual(screen_width, captured.width) self.assertEqual(screen_height, captured.height) # Capture with coordinates captured = display.capture_screen(20, 10, int(screen_width / 2), int(screen_height / 2)) self.assertEqual(int(screen_width / 2), captured.width) self.assertEqual(int(screen_height / 2), captured.height) # Capture with Region region = Region(10, 10, 320, 200) captured = display.capture_screen(region) self.assertEqual(320, captured.width) self.assertEqual(200, captured.height)
def test_position_calc(self): region = Region(10, 20, 300, 200) center = region.center self.assertEqual(160, center.x) self.assertEqual(120, center.y) top_left = region.top_left self.assertEqual(10, top_left.x) self.assertEqual(20, top_left.y) top_right = region.top_right self.assertEqual(310, top_right.x) self.assertEqual(20, top_right.y) bottom_left = region.bottom_left self.assertEqual(10, bottom_left.x) self.assertEqual(220, bottom_left.y) bottom_right = region.bottom_right self.assertEqual(310, bottom_right.x) self.assertEqual(220, bottom_right.y)
class RegionTest(unittest.TestCase): @classmethod def setUpClass(cls): cls.file_resolver = FileResolver() cls.file_resolver.add_path(os.path.join(common_test.unittest_dir, 'images')) # preserve values of static attributes cls.prev_loglevel = GlobalConfig.image_logging_level cls.prev_logpath = GlobalConfig.image_logging_destination GlobalConfig.image_logging_level = 0 GlobalConfig.image_logging_destination = os.path.join(common_test.unittest_dir, 'tmp') @classmethod def tearDownClass(cls): GlobalConfig.image_logging_level = cls.prev_loglevel GlobalConfig.image_logging_destination = cls.prev_logpath def setUp(self): # gui test scripts self.script_app = os.path.join(common_test.unittest_dir, 'qt5_application.py') self.child_app = None # prefixed controls # NOTE: provide and use only fixed locations to avoid CV backend dependencies self.click_control = Location(75, 25) self.double_click_control = Location(185, 20) self.context_menu_control = Location(315, 20) self.context_menu_close_control = Location(355, 35) self.mouse_down_control = Location(435, 95) self.mouse_up_control = Location(435, 135) self.textedit_control = Location(35, 135) self.textedit_quit_control = Location(65, 60) self.textedit_any_control = Location(65, 95) self.drag_control = Location(435, 25) self.drop_control = Location(435, 65) self.region = Region() def tearDown(self): self.close_windows() if os.path.exists(GlobalConfig.image_logging_destination): shutil.rmtree(GlobalConfig.image_logging_destination) def show_application(self): self.child_app = subprocess.Popen(['python3', self.script_app]) # HACK: avoid small variability in loading speed time.sleep(3) def close_windows(self): if self.child_app is not None: self.child_app.terminate() self.wait_end(self.child_app) self.child_app = None # HACK: make sure app is really closed time.sleep(0.5) def wait_end(self, subprocess_pipe, timeout=30): expires = time.time() + timeout while True: exit_code = subprocess_pipe.poll() if exit_code is not None: return exit_code if time.time() > expires: self.fail('Program did not close on time. Ignoring') break time.sleep(0.2) @unittest.skipIf(os.environ.get('DISABLE_AUTOPY', "0") == "1", "AutoPy disabled") def test_get_mouse_location(self): self.region.hover(Location(0, 0)) pos = self.region.mouse_location # Exact match currently not possible, autopy is not pixel perfect. self.assertAlmostEqual(pos.x, 0, delta=1) self.assertAlmostEqual(pos.y, 0, delta=1) self.region.hover(Location(30, 20)) pos = self.region.mouse_location # Exact match currently not possible, autopy is not pixel perfect. self.assertAlmostEqual(pos.x, 30, delta=1) self.assertAlmostEqual(pos.y, 20, delta=1) @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_PYQT', "0") == "1", "Disabled OpenCV or PyQt") def test_hover(self): self.show_application() match = self.region.find('shape_green_box') self.region.hover(match.target) self.assertAlmostEqual(match.target.x, self.region.mouse_location.x, delta=1) self.assertAlmostEqual(match.target.y, self.region.mouse_location.y, delta=1) # hover over coordinates in a subregion match = match.find('shape_green_box') self.assertAlmostEqual(match.target.x, self.region.mouse_location.x, delta=1) self.assertAlmostEqual(match.target.y, self.region.mouse_location.y, delta=1) self.close_windows() @unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_click(self): self.show_application() self.region.click(self.click_control) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_right_click(self): self.show_application() self.region.right_click(self.context_menu_control) self.region.idle(3).click(self.context_menu_close_control) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_double_click(self): self.show_application() self.region.double_click(self.double_click_control) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_multi_click(self): self.show_application() self.region.multi_click(self.click_control, count=1) self.assertEqual(0, self.wait_end(self.child_app)) self.show_application() self.region.multi_click(self.double_click_control, count=2) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_PYQT', "0") == "1", "Disabled OpenCV or PyQt") def test_click_expect(self): self.show_application() self.region.click_expect('shape_green_box') self.close_windows() @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_PYQT', "0") == "1", "Disabled OpenCV or PyQt") def test_click_expect_different(self): self.show_application() self.region.click_expect('shape_green_box', 'shape_black_box') self.close_windows() @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_PYQT', "0") == "1", "Disabled OpenCV or PyQt") def test_click_vanish(self): self.show_application() self.region.click_vanish('shape_red_box') self.close_windows() @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_PYQT', "0") == "1", "Disabled OpenCV or PyQt") def test_click_vanish_different(self): self.show_application() self.region.click_vanish('shape_green_box', 'shape_red_box') self.close_windows() @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_PYQT', "0") == "1", "Disabled OpenCV or PyQt") def test_click_at_index(self): self.show_application() self.region.click_at_index('shape_red_box', 0) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_mouse_down(self): self.show_application() self.region.mouse_down(self.mouse_down_control) # toggled buttons cleanup self.region.dc_backend.mouse_up(self.region.LEFT_BUTTON) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_mouse_up(self): self.show_application() # TODO: the GUI only works if mouse-up event is on the previous location # self.region.mouse_down(Location(0,0)) # self.region.mouse_up(self.mouse_up_control) self.region.mouse_down(self.mouse_up_control) self.region.mouse_up(self.mouse_up_control) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skipIf(os.environ.get('DISABLE_PYAUTOGUI', "0") == "1", "PyAutoGUI disabled") @unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_mouse_scroll(self): # TODO: method not available for other backends self.region.dc_backend = PyAutoGUIController() self.show_application() # TODO: currently we don't have any GUI components for this self.region.mouse_scroll(self.double_click_control) # cleanup since no control can close the window on scroll self.region.dc_backend.mouse_click(count=2) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_drag_drop(self): self.show_application() self.region.drag_drop(self.textedit_control, self.textedit_quit_control) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skip("Unit test either errors out or is expected failure") #@unittest.expectedFailure # hangs with PyQt5 (worked with PyQt4) #@unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_drag_from(self): self.show_application() self.region.drag_from(self.textedit_control) self.region.hover(self.drag_control) # toggled buttons cleanup self.region.dc_backend.mouse_up(self.region.LEFT_BUTTON) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_drop_at(self): self.show_application() self.region.drag_from(self.textedit_control) self.region.drop_at(self.drop_control) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_press_keys(self): self.show_application() time.sleep(1) self.region.press_keys(self.region.ESC) self.assertEqual(0, self.wait_end(self.child_app)) # BUG: Qt fails to register a close event in some cases #self.show_application() #time.sleep(1) #self.region.press_keys([self.region.ALT, self.region.F4]) #self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_press_at(self): self.show_application() self.region.press_at([self.region.ESC], self.textedit_any_control) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_type_text(self): self.show_application() self.region.click(self.textedit_quit_control) self.region.idle(0.2).type_text('quit') self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_type_at(self): self.show_application() self.region.type_at('quit', self.textedit_quit_control) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skipIf(os.environ.get('DISABLE_PYQT', "0") == "1", "PyQt disabled") def test_fill_at(self): self.show_application() self.region.fill_at(self.textedit_quit_control, 'quit', 0, 0) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None @unittest.skip("Skip due to fatal error (breaking the entire run)") #@unittest.expectedFailure # autopy has a bug with arrow keys def test_select_at(self): self.show_application() self.region.right_click(self.context_menu_control) self.region.select_at(self.context_menu_close_control, 1, 0, 0, mark_clicks=0) self.assertEqual(0, self.wait_end(self.child_app)) self.child_app = None
def setUp(self): self.child_img = None # initialize template matching region to support multiple matches GlobalConfig.hybrid_match_backend = "template" self.region = Region()
class RegionTest(unittest.TestCase): @classmethod def setUpClass(cls): cls.file_resolver = FileResolver() cls.file_resolver.add_path(os.path.join(common_test.unittest_dir, 'images')) cls.script_img = os.path.join(common_test.unittest_dir, 'qt5_image.py') # preserve values of static attributes cls.prev_loglevel = GlobalConfig.image_logging_level cls.prev_logpath = GlobalConfig.image_logging_destination GlobalConfig.image_logging_level = 0 GlobalConfig.image_logging_destination = os.path.join(common_test.unittest_dir, 'tmp') @classmethod def tearDownClass(cls): GlobalConfig.image_logging_level = cls.prev_loglevel GlobalConfig.image_logging_destination = cls.prev_logpath def setUp(self): self.child_img = None # initialize template matching region to support multiple matches GlobalConfig.hybrid_match_backend = "template" self.region = Region() def tearDown(self): self.close_windows() if os.path.exists(GlobalConfig.image_logging_destination): shutil.rmtree(GlobalConfig.image_logging_destination) def assertAlmostIn(self, match, matches, delta=5): x, y = match for m in matches: mx, my = m if abs(x - mx) <= delta: if abs(y - my) <= delta: return raise AssertionError("%s not near any of %s" % (match, matches)) def show_image(self, filename): filename = self.file_resolver.search(filename) self.child_img = subprocess.Popen(['python3', self.script_img, filename]) # HACK: avoid small variability in loading speed time.sleep(3) def close_windows(self): if self.child_img is not None: self.child_img.terminate() self.wait_end(self.child_img) self.child_img = None # make sure image is really closed time.sleep(0.5) def wait_end(self, subprocess_pipe, timeout=30): expires = time.time() + timeout while True: exit_code = subprocess_pipe.poll() if exit_code is not None: return exit_code if time.time() > expires: self.fail('Program did not close on time. Ignoring') break time.sleep(0.2) @unittest.skipIf(os.environ.get('DISABLE_AUTOPY', "0") == "1", "AutoPy disabled") def test_initialize(self): screen_width = AutoPyController().width screen_height = AutoPyController().height self.assertEqual(0, self.region.x) self.assertEqual(0, self.region.y) self.assertEqual(screen_width, self.region.width) self.assertEqual(screen_height, self.region.height) region = Region(10, 20, 300, 200) self.assertEqual(10, region.x) self.assertEqual(20, region.y) self.assertEqual(300, region.width) self.assertEqual(200, region.height) @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_PYQT', "0") == "1", "Disabled OpenCV or PyQt") def test_find(self): self.show_image('all_shapes') match = self.region.find(Image('shape_green_box')) self.assertAlmostEqual(match.x, 30, delta=5) self.assertAlmostEqual(match.y, 190, delta=5) self.assertAlmostEqual(70, match.width, delta=5) self.assertAlmostEqual(50, match.height, delta=5) # Match again - this time just pass a filename match = self.region.find('shape_green_box') self.assertAlmostEqual(match.x, 30, delta=5) self.assertAlmostEqual(match.y, 190, delta=5) self.assertAlmostEqual(70, match.width, delta=5) self.assertAlmostEqual(50, match.height, delta=5) # Test last match property last_match = self.region.last_match self.assertEqual(last_match.x, match.x) self.assertEqual(last_match.y, match.y) self.assertEqual(last_match.width, match.width) self.assertEqual(last_match.height, match.height) @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_PYQT', "0") == "1", "Disabled OpenCV or PyQt") def test_find_center_offset(self): self.show_image('all_shapes.png') match = self.region.find(Image('shape_blue_circle.png')) # Positive target offset match_offset = self.region.find(Image('shape_blue_circle.png').with_center_offset(200, 100)) self.assertEqual(match.target.x + 200, match_offset.target.x) self.assertEqual(match.target.y + 100, match_offset.target.y) # Negative target offset match_offset = self.region.find(Image('shape_blue_circle.png').with_center_offset(-50, -30)) self.assertEqual(match.target.x - 50, match_offset.target.x) self.assertEqual(match.target.y - 30, match_offset.target.y) @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_AUTOPY', "0") == "1", "Disabled OpenCV or AutoPy") def test_find_error(self): try: self.region.find(Image('shape_blue_circle.png'), 0) self.fail('exception was not thrown') except FindError as e: pass try: self.region.find_all(Image('shape_blue_circle.png'), 0) self.fail('exception was not thrown') except FindError as e: pass @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_PYQT', "0") == "1", "Disabled OpenCV or PyQt") def test_find_all(self): self.show_image('all_shapes') greenbox = Image('shape_green_box') matches = self.region.find_all(greenbox) self.assertEqual(len(matches), 1) self.assertAlmostEqual(matches[0].x, 30, delta=5) self.assertAlmostEqual(matches[0].y, 190, delta=5) self.assertAlmostEqual(70, matches[0].width, delta=5) self.assertAlmostEqual(50, matches[0].height, delta=5) redbox = Image('shape_red_box') matches = self.region.find_all(redbox) expected_matches = [(25, 25), (320, 25), (315, 115)] self.assertEqual(len(matches), len(expected_matches)) for match in matches: self.region.hover(match) time.sleep(0.5) self.assertAlmostIn((match.x, match.y), expected_matches) self.assertAlmostEqual(70, match.width, delta=5) self.assertAlmostEqual(60, match.height, delta=5) pinkbox = Image('shape_pink_box') # pink is similar to red, so the best fuzzy matches also # include the three red boxes when considering color self.region.cv_backend.matcher.params["find"]["similarity"].value = 0.5 self.region.cv_backend.matcher.params["template"]["nocolor"].value = False matches = self.region.find_all(pinkbox) # approximately the above coordinates since maching different needle expected_matches = [(25, 35), (320, 40), (320, 125), (30, 255)] self.assertEqual(len(matches), len(expected_matches)) for match in matches: self.region.hover(match) time.sleep(0.5) self.assertAlmostIn((match.x, match.y), expected_matches) self.assertAlmostEqual(70, match.width, delta=5) self.assertAlmostEqual(50, match.height, delta=5) # ignore colors here so the best matches for the pink box # should be based on shape (the green and yellow box) self.region.cv_backend.matcher.params["find"]["similarity"].value = 0.8 self.region.cv_backend.matcher.params["template"]["nocolor"].value = True matches = self.region.find_all(pinkbox) expected_matches = [(30, 120), (30, 195), (30, 255)] self.assertEqual(len(matches), len(expected_matches)) for match in matches: self.region.hover(match) time.sleep(0.5) self.assertAlmostIn((match.x, match.y), expected_matches) self.assertAlmostEqual(70, match.width, delta=5) self.assertAlmostEqual(50, match.height, delta=5) @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_PYQT', "0") == "1", "Disabled OpenCV or PyQt") def test_find_zero_matches(self): self.show_image('all_shapes') matches = self.region.find_all(Image('shape_blue_circle')) self.assertEqual(len(matches), 1) self.close_windows() matches = self.region.find_all(Image('shape_blue_circle'), allow_zero=True) self.assertEqual(len(matches), 0) self.close_windows() @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_OCR', "0") == "1", "Disabled OpenCV or OCR") def test_find_guess_target(self): self.show_image('all_shapes') imgroot = os.path.join(common_test.unittest_dir, 'images') # find image from string with and without extension self.assertFalse(os.path.exists(os.path.join(imgroot, 'shape_blue_circle.match'))) self.assertTrue(os.path.exists(os.path.join(imgroot, 'shape_blue_circle.png'))) self.region.find('shape_blue_circle') self.region.find_all('shape_blue_circle') self.region.find('shape_blue_circle.png') self.region.find_all('shape_blue_circle.png') # guess from match file configuration (target has match config) # precedence is given to match file configuration (then data file) self.assertTrue(os.path.exists(os.path.join(imgroot, 'mouse down.match'))) self.assertTrue(os.path.exists(os.path.join(imgroot, 'mouse down.txt'))) try: self.region.find('mouse down') self.fail('exception was not thrown') except FindError as e: pass try: self.region.find_all('mouse down') self.fail('exception was not thrown') except FindError as e: pass # guess from data file extension (target has no match config) self.assertFalse(os.path.exists(os.path.join(imgroot, 'circle.match'))) self.assertTrue(os.path.exists(os.path.join(imgroot, 'circle.steps'))) self.region.find('circle') self.region.find_all('circle') # end with default type if also unknown data type self.assertFalse(os.path.exists(os.path.join(imgroot, 'shape_blue_circle_unknown.match'))) self.assertTrue(os.path.exists(os.path.join(imgroot, 'shape_blue_circle_unknown.xtx'))) self.region.default_target_type = Image # NOTE: autopy cannot handle a masked image self.region.find('shape_blue_circle_unknown.xtx') self.region.find_all('shape_blue_circle_unknown.xtx') # do not fail with default text type if also missing data file self.assertFalse(os.path.exists(os.path.join(imgroot, 'mouse somewhere.match'))) self.assertFalse(os.path.exists(os.path.join(imgroot, 'mouse somewhere.txt'))) self.region.default_target_type = Text self.region.cv_backend = TextFinder() try: self.region.find('mouse somewhere') self.fail('exception was not thrown') except FindError as e: pass try: self.region.find_all('mouse somewhere') self.fail('exception was not thrown') except FindError as e: pass @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_PYQT', "0") == "1", "Disabled OpenCV or PyQt") def test_sample(self): self.show_image('all_shapes') # autopy matching does not support similarity shapes = Region(cv=AutoPyFinder()) similarity = shapes.sample(Image('shape_blue_circle')) self.assertEqual(similarity, 0.0) # initialize template matching region to support similarity shapes = Region(cv=TemplateFinder()) similarity = shapes.sample(Image('shape_blue_circle')) self.assertAlmostEqual(similarity, 0.999999, delta=0.001) self.close_windows() @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_PYQT', "0") == "1", "Disabled OpenCV or PyQt") def test_exists(self): self.show_image('all_shapes') match = self.region.find(Image('shape_blue_circle')) self.assertTrue(isinstance(match, Match)) self.close_windows() match = self.region.exists(Image('shape_blue_circle')) self.assertEqual(None, match) @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_PYQT', "0") == "1", "Disabled OpenCV or PyQt") def test_wait(self): self.show_image('all_shapes') match = self.region.wait(Image('shape_blue_circle'), timeout=5) self.assertTrue(isinstance(match, Match)) self.close_windows() @unittest.skipIf(os.environ.get('DISABLE_OPENCV', "0") == "1" or os.environ.get('DISABLE_PYQT', "0") == "1", "Disabled OpenCV or PyQt") def test_wait_vanish(self): self.show_image('all_shapes') self.assertRaises(NotFindError, self.region.wait_vanish, 'all_shapes', timeout=10) self.close_windows() # assert no NotFindError is raised now self.assertTrue(self.region.wait_vanish('all_shapes', timeout=10))