def pytest_sessionstart(session):
    """ before session.main() is called. """
    filename = "pytest.ini"
    head = util.get_proyect_root_path()

    # Get behave ini config
    pytest.cfg = util.read_config_file(head + "/" + filename)

    sut_url = pytest.cfg.get('pytest.environment.local').get('sut_url')
    env_name = pytest.cfg.get('pytest.environment.local').get('env_name')

    import platform

    # TODO: Synchronize context "date_run" timestamp and screenshot timestamp
    pytest.execution_data = dict({
        "sut_url": sut_url,
        "environment": env_name,
        "project_root": head,
        "platform": platform.system().lower(),
        "driver": None,
        "video_recording": None,
        "run_id": None,
        "date_run": util.get_time_stamp(),
        "feature_name": None,
        "scenario_name": None,
        "window_size": None,
        "image_output_path": head + pytest.cfg.get('pytest').get('images_output_path'),
        "rest": {}
    })
Beispiel #2
0
    def __init__(self, class_name):
        self.screenshot_output_folder_path = util.get_proyect_root_path() + \
                                             util.read_config_file("behave.ini")["behave"]["images_output_path"]
        self.screenshot_file_name = class_name.lower() + "_SCREENSHOT" + ".png"
        self.full_image_output_path = self.screenshot_output_folder_path + self.screenshot_file_name

        self.result_img_path = self.screenshot_output_folder_path + class_name + "_MATCHING_RESULT" + ".png"
class MacOsDesktopPagePageElements:
    __project_root_path = util.get_proyect_root_path()
    desktop_image_path = __project_root_path + "/reports/visual_image_testing/MacOsDesktopPage.png"
    threshold = 0.99

    # Login Locator
    icon_launchpad_path = __project_root_path + "/page_object_elements/image/macos/desktop/target/icon_launchpad.png"
    icon_launchpad = ImageDesktopPageElement(
        locator=icon_launchpad_path,
        desktop_image_path=desktop_image_path,
        threshold=0.95)
class RedmineLoginByImagePagePageElements:
    __project_root_path = util.get_proyect_root_path()
    browser_image_path = __project_root_path + "/reports/visual_image_testing/RedmineLoginByImagePage_SCREENSHOT.png"
    threshold = 0.99

    # Home Standard Image
    login_page_standard_path = (
        By.IMAGE, __project_root_path +
        "/page_object_elements/image/redmine/login_page/standard/login_page.png",
        browser_image_path)
    login_page_standard = ImageWebdriverPageElement(login_page_standard_path)

    # Login Locator
    txt_login_in_path = (
        By.IMAGE, __project_root_path +
        "/page_object_elements/image/redmine/login_page/target/txt_login.png",
        browser_image_path)

    txt_login_in = ImageWebdriverPageElement(txt_login_in_path, threshold=0.74)

    # Password Locator
    txt_password_path = (
        By.IMAGE, __project_root_path +
        "/page_object_elements/image/redmine/login_page/target/txt_password.png",
        browser_image_path)

    txt_password = ImageWebdriverPageElement(txt_password_path,
                                             threshold=threshold)

    # Login button Locator
    btn_login_path = (
        By.IMAGE, __project_root_path +
        "/page_object_elements/image/redmine/login_page/target/btn_login.png",
        browser_image_path)

    btn_login = ImageWebdriverPageElement(btn_login_path, threshold=threshold)

    # Lost Password Locator
    btn_lost_password_path = (
        By.IMAGE, __project_root_path +
        "/page_object_elements/image/redmine/login_page/target/bnt_lost_password.png",
        browser_image_path)

    btn_lost_password = ImageWebdriverPageElement(btn_lost_password_path,
                                                  threshold=threshold)
Beispiel #5
0
class MacOsLaunchpadPagePageElements:
    __project_root_path = util.get_proyect_root_path()
    desktop_image_path = __project_root_path + "/reports/visual_image_testing/MacOsDesktopPage.png"
    default_threshold = 0.99

    # Search App Locator
    txt_search_app_loc = __project_root_path + "/page_object_elements/image/macos/desktop/target/txt_search_app.png"
    txt_search_app = ImageDesktopPageElement(
        locator=txt_search_app_loc,
        desktop_image_path=desktop_image_path,
        threshold=default_threshold)

    # Search App Locator
    icon_reminders_loc = __project_root_path + "/page_object_elements/image/macos/desktop/target/icon_reminders.png"
    icon_reminders = ImageDesktopPageElement(
        locator=icon_reminders_loc,
        desktop_image_path=desktop_image_path,
        threshold=0.80)
class RedmineHomepageByImagePagePageElements:
    __project_root_path = util.get_proyect_root_path()
    browser_image_path = __project_root_path + "/reports/visual_image_testing/RedmineHomepageByImagePage_SCREENSHOT.png"

    # Home Standard Image
    home_page_standard_path = (
        By.IMAGE, __project_root_path +
        "/page_object_elements/image/redmine/home_page/standard/home_page.png",
        browser_image_path)
    home_page_image = ImageWebdriverPageElement(home_page_standard_path)

    # Sign in Locator
    btn_sign_in_path = (
        By.IMAGE, __project_root_path +
        "/page_object_elements/image/redmine/home_page/target/sign_in_btn.png",
        browser_image_path)

    btn_sign_in = ImageWebdriverPageElement(btn_sign_in_path)

    # Register Locator
    btn_register_path = (
        By.IMAGE, __project_root_path +
        "/page_object_elements/image/redmine/home_page/target/register_btn.png",
        browser_image_path)

    btn_register = ImageWebdriverPageElement(btn_register_path)

    # Home Locator
    btn_home_path = (
        By.IMAGE, __project_root_path +
        "/page_object_elements/image/redmine/home_page/target/home_btn.png",
        browser_image_path)

    btn_home = ImageWebdriverPageElement(btn_home_path)

    # Home Locator
    btn_projects_path = (
        By.IMAGE, __project_root_path +
        "/page_object_elements/image/redmine/home_page/target/projects_btn.png",
        browser_image_path)

    btn_projects = ImageWebdriverPageElement(btn_projects_path)
Beispiel #7
0
class MacOsRemindersPagePageElements:
    __project_root_path = util.get_proyect_root_path()
    desktop_image_path = __project_root_path + "/reports/visual_image_testing/MacOsRemindersPage.png"
    reminder_standard_image_path = __project_root_path + "/page_object_elements/image/macos/reminder/standard/reminders_main_standard.png"
    default_threshold = 0.99

    # Reminder Name prompt
    txt_reminder_name_prompt_loc = __project_root_path + \
                                   "/page_object_elements/image/macos/reminder/target/txt_reminders_prompt.png"
    txt_reminder_name_prompt = ImageDesktopPageElement(
        locator=txt_reminder_name_prompt_loc,
        desktop_image_path=desktop_image_path,
        threshold=0.95)
    # Reminder Name
    txt_reminder_name_loc = __project_root_path + \
                            "/page_object_elements/image/macos/reminder/target/txt_reminder_name.png"
    txt_reminder_name = ImageDesktopPageElement(
        locator=txt_reminder_name_loc,
        desktop_image_path=desktop_image_path,
        threshold=0.90)

    # Add Reminder button
    btn_add_reminder_method = "TM_CCOEFF_NORMED"
    btn_add_reminder_loc = __project_root_path + \
                           "/page_object_elements/image/macos/reminder/target/btn_add_reminder.png"

    btn_add_reminder = ImageDesktopPageElement(
        locator=btn_add_reminder_loc,
        desktop_image_path=desktop_image_path,
        method=btn_add_reminder_method,
        threshold=0.99)
    # File Menu
    menu_file_loc = __project_root_path + \
                    "/page_object_elements/image/macos/reminder/target/menu_file.png"
    menu_file = ImageDesktopPageElement(locator=menu_file_loc,
                                        desktop_image_path=desktop_image_path,
                                        threshold=0.90)

    # File >> New Reminder
    menu_file_new_reminder_loc = __project_root_path + \
                                 "/page_object_elements/image/macos/reminder/target/menu_file_new_reminder.png"
    menu_file_new_reminder = ImageDesktopPageElement(
        locator=menu_file_new_reminder_loc,
        desktop_image_path=desktop_image_path,
        threshold=0.90)
    # Button info
    btn_info_loc = __project_root_path + \
                   "/page_object_elements/image/macos/reminder/target/btn_info.png"
    btn_info_method = "TM_CCOEFF"
    btn_info = ImageDesktopPageElement(locator=btn_info_loc,
                                       desktop_image_path=desktop_image_path,
                                       threshold=0.80)

    # Context Menu - Show info
    context_menu_show_info_loc = __project_root_path + \
                                 "/page_object_elements/image/macos/reminder/target/context_menu_show_info.png"
    context_menu_show_info = ImageDesktopPageElement(
        locator=context_menu_show_info_loc,
        desktop_image_path=desktop_image_path,
        threshold=0.80)
    # On a day
    chk_on_a_day_loc = __project_root_path + \
                       "/page_object_elements/image/macos/reminder/target/chk_on_a_day.png"
    chk_on_a_day = ImageDesktopPageElement(
        locator=chk_on_a_day_loc,
        desktop_image_path=desktop_image_path,
        threshold=0.85)

    # Priority
    sel_priority_loc = __project_root_path + \
                       "/page_object_elements/image/macos/reminder/target/sel_priority.png"
    sel_priority = ImageDesktopPageElement(
        locator=sel_priority_loc,
        desktop_image_path=desktop_image_path,
        threshold=0.90)

    # Priority Low
    sel_priority_low_loc = __project_root_path + \
                           "/page_object_elements/image/macos/reminder/target/sel_priority_low.png"

    sel_priority_low = ImageDesktopPageElement(
        locator=sel_priority_low_loc,
        desktop_image_path=desktop_image_path,
        threshold=0.90)

    # Priority Medium
    sel_priority_medium_loc = __project_root_path + \
                              "/page_object_elements/image/macos/reminder/target/sel_priority_medium.png"
    sel_priority_medium = ImageDesktopPageElement(
        locator=sel_priority_medium_loc,
        desktop_image_path=desktop_image_path,
        threshold=0.90)

    # Priority high
    sel_priority_high_loc = __project_root_path + \
                            "/page_object_elements/image/macos/reminder/target/sel_priority_high.png"
    sel_priority_high = ImageDesktopPageElement(
        locator=sel_priority_high_loc,
        desktop_image_path=desktop_image_path,
        threshold=0.90)
    # Notes
    txt_note_loc = __project_root_path + \
                   "/page_object_elements/image/macos/reminder/target/txt_note.png"
    txt_note = ImageDesktopPageElement(locator=txt_note_loc,
                                       desktop_image_path=desktop_image_path,
                                       threshold=0.95)

    # Done
    btn_done_loc = __project_root_path + \
                   "/page_object_elements/image/macos/reminder/target/btn_done.png"
    btn_done = ImageDesktopPageElement(locator=btn_done_loc,
                                       desktop_image_path=desktop_image_path,
                                       threshold=0.90)

    # View Menu
    menu_view_loc = __project_root_path + \
                   "/page_object_elements/image/macos/reminder/target/menu_view.png"
    menu_view = ImageDesktopPageElement(locator=menu_view_loc,
                                        desktop_image_path=desktop_image_path,
                                        threshold=0.90)

    # View Menu >> Enter Full screen
    menu_view_enter_full_screen_loc = __project_root_path + \
                   "/page_object_elements/image/macos/reminder/target/menu_view_enter_full_screen.png"
    menu_view_enter_full_screen = ImageDesktopPageElement(
        locator=menu_view_enter_full_screen_loc,
        desktop_image_path=desktop_image_path,
        threshold=0.90)

    # Send lbl_send_the_weekly_report
    lbl_send_the_weekly_report_loc = __project_root_path + \
                                      "/page_object_elements/image/macos/reminder/target/lbl_send_the_weekly_report.png"
    lbl_send_the_weekly_report = ImageDesktopPageElement(
        locator=lbl_send_the_weekly_report_loc,
        desktop_image_path=desktop_image_path,
        threshold=0.85)

    # Send lbl_send_the_weekly_report
    context_menu_delete_loc = __project_root_path + \
                                     "/page_object_elements/image/macos/reminder/target/context_menu_delete.png"
    context_menu_delete = ImageDesktopPageElement(
        locator=context_menu_delete_loc,
        desktop_image_path=desktop_image_path,
        threshold=0.95)
Beispiel #8
0
class ImageBaseHandler:
    PROJECT_ROOT = util.get_proyect_root_path()
    STANDARD_WATERMARK_IMG_PATH = PROJECT_ROOT + "/templates/watermarks/standard.png"
    RESULT_WATERMARK_IMG_PATH = PROJECT_ROOT + "/templates/watermarks/result.png"
    DIFFERENCES_WATERMARK_IMG_PATH = PROJECT_ROOT + "/templates/watermarks//differences.png"

    rectangle_thickness = 2
    rectangle_color = (0, 0, 255)
    threshold = 0.99

    def __init__(self,
                 target_img_path,
                 full_img_path,
                 result_img_path,
                 threshold=None,
                 window_size=None):
        # Target Image
        self.target_img_path = target_img_path
        self.target_img = None

        # Screenshot Image
        self.full_img_path = full_img_path
        self.full_img = None

        # Result image
        self.result_img_path = result_img_path
        self.result_img = None

        self.img_occurrences = []
        self.occurrences = None
        self.threshold = threshold if threshold is not None else self.threshold
        self.standard_minus_current_difference = None
        self.matching_img_y_cord = None
        self.matching_img_x_cord = None
        self.target_img_height = None
        self.target_img_width = None

        self.window_size = window_size

    def set_result_img_path(self, result_img_path):
        self.result_img_path = result_img_path

    def set_threshold(self, threshold):
        self.threshold = threshold

    def get_threshold(self):
        return self.threshold

    def set_windows_size(self, windows_size):
        self.window_size = windows_size

    def set_target_image_path(self, target_path):
        self.target_img_path = target_path

    def set_full_image_path(self, full_image_path):
        self.full_img_path = full_image_path

    def find_img_on_screen(self,
                           full_img_path=None,
                           target_img_path=None,
                           draw_rectangle=False):
        """
        Find target image in another image.
        :param target_img_path: Path to target image to be found in screenshot image
        :param full_img_path: Path to full image
        :param draw_rectangle: If a rectangle should be drawn in the full image showing the matching result.
        :return:
        """

        if target_img_path is None:
            if self.target_img_path is None:
                raise Exception("You must specify a target path.")
        else:
            self.target_img_path = target_img_path

        if full_img_path is None:
            if self.full_img_path is None:
                raise Exception("You must specify a screenshot path.")
        else:
            self.full_img_path = full_img_path

        self.target_img = self.get_image(image_path=self.target_img_path)
        self.full_img = self.get_image(image_path=self.full_img_path)

        # Looking for a target image in full image
        self.result_img = self.find_matching(target_img=self.target_img,
                                             full_image=self.full_img,
                                             method=cv2.TM_CCOEFF_NORMED)

        if self.is_image_found(result=self.result_img):
            if draw_rectangle:
                self.draw_rectangle_on_image(full_image=self.full_img,
                                             target_img=self.target_img)
            return True
        else:
            return False

    def find_matching(self, target_img, full_image, method):

        result = cv2.matchTemplate(image=target_img,
                                   templ=full_image,
                                   method=method)

        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
        top_left = max_loc

        self.target_img_height, self.target_img_width = target_img.shape[:-1]

        self.matching_img_y_cord = top_left[1] + int(
            self.target_img_height / 2)
        self.matching_img_x_cord = top_left[0] + int(self.target_img_width / 2)

        return result

    @staticmethod
    def get_template_matching_method(method):

        if method is None:
            return "TM_CCOEFF_NORMED", cv2.TM_CCOEFF_NORMED
        else:
            method = method.upper()

        if method == "TM_CCOEFF_NORMED":
            return "TM_CCOEFF_NORMED", cv2.TM_CCOEFF_NORMED
        elif method == "TM_CCOEFF":
            return method, cv2.TM_CCOEFF
        elif method == "TM_CCORR":
            return method, cv2.TM_CCORR
        elif method == "TM_CCORR_NORMED":
            return method, cv2.TM_CCORR_NORMED
        elif method == "TM_SQDIFF":
            return method, cv2.TM_SQDIFF
        elif method == "TM_SQDIFF_NORMED":
            return method, cv2.TM_SQDIFF_NORMED
        else:
            raise Exception(
                4 * "<" + "[ERROR]" + 4 * ">" + "\n" +
                "Template Matching Method does not exist or is not supported: "
                + "\n" + method + "\n")

    @staticmethod
    def get_image(image_path, flags=None) -> np.ndarray:
        result_img = cv2.imread(image_path)
        if result_img is None:
            raise Exception(4 * "<" + "[ERROR]" + 4 * ">" + "\n" +
                            "Image is invalid or does not exist: " +
                            image_path + "\n")

        return result_img

    def draw_rectangle_on_image(self, full_image: np.ndarray,
                                target_img: np.ndarray):
        h, w = target_img.shape[:-1]
        self.img_occurrences = []

        for pt in zip(*self.occurrences[::-1]):
            x = pt[0] + int(w / 2)
            y = pt[1] + int(h / 2)

            self.img_occurrences.append((x, y))

            cv2.rectangle(img=full_image,
                          pt1=pt,
                          pt2=(pt[0] + w, pt[1] + h),
                          color=self.rectangle_color,
                          thickness=self.rectangle_thickness)

            cv2.circle(img=full_image,
                       center=(x, y),
                       radius=1,
                       color=(255, 0, 255),
                       thickness=self.rectangle_thickness)

        cv2.imwrite(self.result_img_path, full_image)

    def is_image_found(self, result: np.ndarray, threshold=None) -> bool:
        if threshold is None:
            threshold = self.threshold

        self.occurrences = np.where(result >= threshold)

        return False if self.occurrences[0].shape[0] == 0 else True

    def compare_images(self):
        self.target_img = self.get_image(self.target_img_path)
        self.full_img = self.get_image(self.full_img_path)

        # Differences found
        self.standard_minus_current_difference = cv2.absdiff(
            self.target_img, self.full_img)

        # Creates the images comparison collage

        diff_compare = cv2.absdiff(self.target_img, self.full_img)

        standard = cv2.copyMakeBorder(self.target_img,
                                      1,
                                      1,
                                      1,
                                      1,
                                      cv2.BORDER_CONSTANT,
                                      value=[255, 0, 0])

        standard = self.apply_watermark(
            image=standard,
            watermark_img_path=self.STANDARD_WATERMARK_IMG_PATH)

        screenshot = cv2.copyMakeBorder(self.full_img,
                                        1,
                                        1,
                                        1,
                                        1,
                                        cv2.BORDER_CONSTANT,
                                        value=[255, 0, 0])

        screenshot = self.apply_watermark(
            image=screenshot,
            watermark_img_path=self.RESULT_WATERMARK_IMG_PATH)

        differences = cv2.copyMakeBorder(diff_compare,
                                         1,
                                         1,
                                         1,
                                         1,
                                         cv2.BORDER_CONSTANT,
                                         value=[255, 0, 0])

        differences = self.apply_watermark(
            image=differences,
            watermark_img_path=self.DIFFERENCES_WATERMARK_IMG_PATH)

        temp4 = np.hstack((standard, screenshot))

        diff_compare = np.hstack((temp4, differences))

        cv2.imwrite(filename=self.result_img_path, img=diff_compare)

        return self.standard_minus_current_difference

    def is_difference_found(self, standard_img_path=None, full_img_path=None):
        self.standard_minus_current_difference = self.compare_images()

        if self.standard_minus_current_difference is None:
            raise Exception(
                4 * "<" + "[ERROR]" + 4 * ">" + "\n" +
                "standard_minus_current_difference variable cannot be None" +
                "\n")

        b, g, r = cv2.split(self.standard_minus_current_difference)

        if cv2.countNonZero(b) == 0 and cv2.countNonZero(
                g) == 0 and cv2.countNonZero(r) == 0:
            return False
        else:
            return True

    @staticmethod
    def apply_watermark(image, watermark_img_path, position=(10, 10)):
        # Coordinates where to put the watermark
        cx, cy = position

        # Reading the image
        (h, w) = image.shape[:2]
        image = np.dstack([image, np.ones((h, w), dtype="uint8") * 255])

        # Reading the watermark
        watermark_img = cv2.imread(watermark_img_path, cv2.IMREAD_UNCHANGED)
        (wH, wW) = watermark_img.shape[:2]
        (B, G, R, A) = cv2.split(watermark_img)
        B = cv2.bitwise_and(B, B, mask=A)
        G = cv2.bitwise_and(G, G, mask=A)
        R = cv2.bitwise_and(R, R, mask=A)
        watermark = cv2.merge([B, G, R, A])

        # Creating the image's overlay with the watermark
        overlay = np.zeros((h, w, 4), dtype="uint8")
        overlay[cy:wH + cy, cx:wW + cx] = watermark

        # Applying the overlay
        output = image.copy()
        return cv2.addWeighted(overlay, 0.4, output, 1.0, 0, output)