Esempio n. 1
0
    def save_webdriver_logs_by_type(self, log_type, test_name):
        """Get webdriver logs of the specified type and write them to a log file

        :param log_type: browser, client, driver, performance, server, syslog, crashlog or logcat
        :param test_name: test that has generated these logs
        """
        try:
            logs = self.driver_wrapper.driver.get_log(log_type)
        except Exception:
            return

        if len(logs) > 0:
            log_file_name = '{}_{}.txt'.format(get_valid_filename(test_name),
                                               log_type)
            log_file_name = os.path.join(DriverWrappersPool.logs_directory,
                                         log_file_name)
            with open(log_file_name, 'a+', encoding='utf-8') as log_file:
                driver_type = self.driver_wrapper.config.get('Driver', 'type')
                log_file.write(
                    u"\n{} '{}' test logs with driver = {}\n\n".format(
                        datetime.now(), test_name, driver_type))
                for entry in logs:
                    timestamp = datetime.fromtimestamp(
                        float(entry['timestamp']) /
                        1000.).strftime('%Y-%m-%d %H:%M:%S.%f')
                    log_file.write(u'{}\t{}\t{}\n'.format(
                        timestamp, entry['level'], entry['message'].rstrip()))
    def configure_visual_directories(cls, driver_info):
        """Configure screenshots, videos and visual directories

        :param driver_info: driver property value to name folders
        """
        if cls.screenshots_directory is None:
            # Unique screenshots and videos directories
            date = datetime.datetime.now().strftime('%Y-%m-%d_%H%M%S')
            folder_name = '%s_%s' % (date,
                                     driver_info) if driver_info else date
            folder_name = get_valid_filename(folder_name)
            cls.screenshots_directory = os.path.join(cls.output_directory,
                                                     'screenshots',
                                                     folder_name)
            cls.screenshots_number = 1
            cls.videos_directory = os.path.join(cls.output_directory, 'videos',
                                                folder_name)
            cls.logs_directory = os.path.join(cls.output_directory, 'logs',
                                              folder_name)
            cls.videos_number = 1

            # Unique visualtests directories
            cls.visual_output_directory = os.path.join(cls.output_directory,
                                                       'visualtests',
                                                       folder_name)
            cls.visual_number = 1
Esempio n. 3
0
    def __init__(self, driver_wrapper=None, force=False):
        self.driver_wrapper = driver_wrapper if driver_wrapper else DriverWrappersPool.get_default_wrapper(
        )
        self.force = force
        if not self.driver_wrapper.config.getboolean_optional(
                'VisualTests', 'enabled') and not self.force:
            return
        if 'PerceptualEngine' not in globals():
            raise Exception(
                'The visual tests are enabled, but needle is not installed')

        self.utils = self.driver_wrapper.utils
        self.logger = logging.getLogger(__name__)
        self.output_directory = DriverWrappersPool.visual_output_directory

        # Update baseline with real platformVersion value
        if '{platformVersion}' in self.driver_wrapper.baseline_name:
            platform_version = self.driver_wrapper.driver.desired_capabilities[
                'platformVersion']
            baseline_name = self.driver_wrapper.baseline_name.replace(
                '{platformVersion}', platform_version)
            self.driver_wrapper.baseline_name = baseline_name
            self.driver_wrapper.visual_baseline_directory = os.path.join(
                DriverWrappersPool.visual_baseline_directory,
                get_valid_filename(baseline_name))

        self.baseline_directory = self.driver_wrapper.visual_baseline_directory
        self.engine = self._get_engine()
        self.save_baseline = self.driver_wrapper.config.getboolean_optional(
            'VisualTests', 'save')

        # Create folders
        if not os.path.exists(self.baseline_directory):
            os.makedirs(self.baseline_directory)
        if not os.path.exists(self.output_directory):
            os.makedirs(self.output_directory)

        # Copy js, css and html template to output directory
        dst_template_path = os.path.join(self.output_directory,
                                         self.report_name)
        if not os.path.exists(dst_template_path):
            resources_path = os.path.join(
                os.path.dirname(os.path.realpath(__file__)), 'resources')
            orig_template_path = os.path.join(resources_path,
                                              self.template_name)
            orig_javascript_path = os.path.join(resources_path,
                                                self.javascript_name)
            dst_javascript_path = os.path.join(self.output_directory,
                                               self.javascript_name)
            orig_css_path = os.path.join(resources_path, self.css_name)
            dst_css_path = os.path.join(self.output_directory, self.css_name)
            shutil.copyfile(orig_template_path, dst_template_path)
            shutil.copyfile(orig_javascript_path, dst_javascript_path)
            shutil.copyfile(orig_css_path, dst_css_path)
            self._add_summary_to_report()
Esempio n. 4
0
    def assert_screenshot(self, element, filename, file_suffix=None, threshold=0, exclude_elements=[]):
        """Assert that a screenshot of an element is the same as a screenshot on disk, within a given threshold

        :param element: either a WebElement, PageElement or element locator as a tuple (locator_type, locator_value).
                        If None, a full screenshot is taken.
        :param filename: the filename for the screenshot, which will be appended with ``.png``
        :param file_suffix: a string to be appended to the output filename with extra info about the test.
        :param threshold: percentage threshold for triggering a test failure (value between 0 and 1)
        :param exclude_elements: list of WebElements, PageElements or element locators as a tuple (locator_type,
                                 locator_value) that must be excluded from the assertion
        """
        if not self.driver_wrapper.config.getboolean_optional('VisualTests', 'enabled') and not self.force:
            return
        if not (isinstance(threshold, int) or isinstance(threshold, float)) or threshold < 0 or threshold > 1:
            raise TypeError('Threshold must be a number between 0 and 1: {}'.format(threshold))

        # Search elements
        web_element = self.utils.get_web_element(element)
        exclude_web_elements = []
        for exclude_element in exclude_elements:
            try:
                exclude_web_elements.append(self.utils.get_web_element(exclude_element))
            except NoSuchElementException as e:
                self.logger.warning("Element to be excluded not found: %s", str(e))

        baseline_file = os.path.join(self.baseline_directory, '{}.png'.format(filename))
        filename_with_suffix = '{0}__{1}'.format(filename, file_suffix) if file_suffix else filename
        unique_name = '{0:0=2d}_{1}'.format(DriverWrappersPool.visual_number, filename_with_suffix)
        unique_name = '{}.png'.format(get_valid_filename(unique_name))
        output_file = os.path.join(self.output_directory, unique_name)
        report_name = '{}<br>({})'.format(file_suffix, filename) if file_suffix else '-<br>({})'.format(filename)

        # Get screenshot and modify it
        img = Image.open(BytesIO(self.driver_wrapper.driver.get_screenshot_as_png()))
        img = self.remove_scrolls(img)
        img = self.mobile_resize(img)
        img = self.exclude_elements(img, exclude_web_elements)
        img = self.crop_element(img, web_element)
        img.save(output_file)
        DriverWrappersPool.visual_number += 1

        # Determine whether we should save the baseline image
        if self.save_baseline or not os.path.exists(baseline_file):
            # Copy screenshot to baseline
            shutil.copyfile(output_file, baseline_file)

            if self.driver_wrapper.config.getboolean_optional('VisualTests', 'complete_report'):
                self._add_result_to_report('baseline', report_name, output_file, None, 'Screenshot added to baseline')

            self.logger.debug("Visual screenshot '%s' saved in visualtests/baseline folder", filename)
        else:
            # Compare the screenshots
            self.compare_files(report_name, output_file, baseline_file, threshold)
Esempio n. 5
0
    def configure_visual_baseline(self):
        """Configure baseline directory"""
        # Get baseline name
        baseline_name = self.config.get_optional('VisualTests', 'baseline_name', '{Driver_type}')
        for section in self.config.sections():
            for option in self.config.options(section):
                option_value = self.config.get(section, option)
                baseline_name = baseline_name.replace('{{{0}_{1}}}'.format(section, option), option_value)

        # Configure baseline directory if baseline name has changed
        if self.baseline_name != baseline_name:
            self.baseline_name = baseline_name
            self.visual_baseline_directory = os.path.join(DriverWrappersPool.visual_baseline_directory,
                                                          get_valid_filename(baseline_name))
Esempio n. 6
0
    def _download_video(self, video_url, video_name):
        """Download a video from the remote node

        :param video_url: video url
        :param video_name: video name
        """
        filename = '{0:0=2d}_{1}'.format(DriverWrappersPool.videos_number, video_name)
        filename = '{}.mp4'.format(get_valid_filename(filename))
        filepath = os.path.join(DriverWrappersPool.videos_directory, filename)
        if not os.path.exists(DriverWrappersPool.videos_directory):
            os.makedirs(DriverWrappersPool.videos_directory)
        response = requests.get(video_url)
        open(filepath, 'wb').write(response.content)
        self.logger.info("Video saved in '%s'", filepath)
        DriverWrappersPool.videos_number += 1
Esempio n. 7
0
    def _download_video(self, video_url, video_name):
        """Download a video from the remote node

        :param video_url: video url
        :param video_name: video name
        """
        filename = '{0:0=2d}_{1}'.format(DriverWrappersPool.videos_number, video_name)
        filename = '{}.mp4'.format(get_valid_filename(filename))
        filepath = os.path.join(DriverWrappersPool.videos_directory, filename)
        if not os.path.exists(DriverWrappersPool.videos_directory):
            os.makedirs(DriverWrappersPool.videos_directory)
        response = requests.get(video_url)
        open(filepath, 'wb').write(response.content)
        self.logger.info("Video saved in '%s'", filepath)
        DriverWrappersPool.videos_number += 1
Esempio n. 8
0
    def capture_screenshot(self, name):
        """Capture screenshot and save it in screenshots folder

        :param name: screenshot name suffix
        :returns: screenshot path
        """
        filename = '{0:0=2d}_{1}'.format(DriverWrappersPool.screenshots_number, name)
        filename = '{}.png'.format(get_valid_filename(filename))
        filepath = os.path.join(DriverWrappersPool.screenshots_directory, filename)
        if not os.path.exists(DriverWrappersPool.screenshots_directory):
            os.makedirs(DriverWrappersPool.screenshots_directory)
        if self.driver_wrapper.driver.get_screenshot_as_file(filepath):
            self.logger.info('Screenshot saved in %s', filepath)
            DriverWrappersPool.screenshots_number += 1
            return filepath
        return None
Esempio n. 9
0
    def capture_screenshot(self, name):
        """Capture screenshot and save it in screenshots folder

        :param name: screenshot name suffix
        :returns: screenshot path
        """
        filename = '{0:0=2d}_{1}'.format(DriverWrappersPool.screenshots_number, name)
        filename = '{}.png'.format(get_valid_filename(filename))
        filepath = os.path.join(DriverWrappersPool.screenshots_directory, filename)
        if not os.path.exists(DriverWrappersPool.screenshots_directory):
            os.makedirs(DriverWrappersPool.screenshots_directory)
        if self.driver_wrapper.driver.get_screenshot_as_file(filepath):
            self.logger.info('Screenshot saved in %s', filepath)
            DriverWrappersPool.screenshots_number += 1
            return filepath
        return None
Esempio n. 10
0
    def configure_visual_baseline(self):
        """Configure baseline directory"""
        # Get baseline name
        baseline_name = self.config.get_optional('VisualTests',
                                                 'baseline_name',
                                                 '{Driver_type}')
        for section in self.config.sections():
            for option in self.config.options(section):
                option_value = self.config.get(section, option)
                baseline_name = baseline_name.replace(
                    '{{{0}_{1}}}'.format(section, option), option_value)

        # Configure baseline directory if baseline name has changed
        if self.baseline_name != baseline_name:
            self.baseline_name = baseline_name
            self.visual_baseline_directory = os.path.join(
                DriverWrappersPool.visual_baseline_directory,
                get_valid_filename(baseline_name))
Esempio n. 11
0
    def configure_visual_directories(cls, driver_info):
        """Configure screenshots, videos and visual directories

        :param driver_info: driver property value to name folders
        """
        if cls.screenshots_directory is None:
            # Unique screenshots and videos directories
            date = datetime.datetime.now().strftime('%Y-%m-%d_%H%M%S')
            folder_name = '%s_%s' % (date, driver_info) if driver_info else date
            folder_name = get_valid_filename(folder_name)
            cls.screenshots_directory = os.path.join(cls.output_directory, 'screenshots', folder_name)
            cls.screenshots_number = 1
            cls.videos_directory = os.path.join(cls.output_directory, 'videos', folder_name)
            cls.videos_number = 1

            # Unique visualtests directories
            cls.visual_output_directory = os.path.join(cls.output_directory, 'visualtests', folder_name)
            cls.visual_number = 1
Esempio n. 12
0
    def __init__(self, driver_wrapper=None, force=False):
        self.driver_wrapper = driver_wrapper if driver_wrapper else DriverWrappersPool.get_default_wrapper()
        self.force = force
        if not self.driver_wrapper.config.getboolean_optional('VisualTests', 'enabled') and not self.force:
            return
        if 'PerceptualEngine' not in globals():
            raise Exception('The visual tests are enabled, but needle is not installed')

        self.utils = self.driver_wrapper.utils
        self.logger = logging.getLogger(__name__)
        self.output_directory = DriverWrappersPool.visual_output_directory

        # Update baseline with real platformVersion value
        if '{platformVersion}' in self.driver_wrapper.baseline_name:
            platform_version = self.driver_wrapper.driver.desired_capabilities['platformVersion']
            baseline_name = self.driver_wrapper.baseline_name.replace('{platformVersion}', platform_version)
            self.driver_wrapper.baseline_name = baseline_name
            self.driver_wrapper.visual_baseline_directory = os.path.join(DriverWrappersPool.visual_baseline_directory,
                                                                         get_valid_filename(baseline_name))

        self.baseline_directory = self.driver_wrapper.visual_baseline_directory
        self.engine = self._get_engine()
        self.save_baseline = self.driver_wrapper.config.getboolean_optional('VisualTests', 'save')

        # Create folders
        if not os.path.exists(self.baseline_directory):
            os.makedirs(self.baseline_directory)
        if not os.path.exists(self.output_directory):
            os.makedirs(self.output_directory)

        # Copy js, css and html template to output directory
        dst_template_path = os.path.join(self.output_directory, self.report_name)
        if not os.path.exists(dst_template_path):
            resources_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'resources')
            orig_template_path = os.path.join(resources_path, self.template_name)
            orig_javascript_path = os.path.join(resources_path, self.javascript_name)
            dst_javascript_path = os.path.join(self.output_directory, self.javascript_name)
            orig_css_path = os.path.join(resources_path, self.css_name)
            dst_css_path = os.path.join(self.output_directory, self.css_name)
            shutil.copyfile(orig_template_path, dst_template_path)
            shutil.copyfile(orig_javascript_path, dst_javascript_path)
            shutil.copyfile(orig_css_path, dst_css_path)
            self._add_summary_to_report()
    def download_videos(cls, name, test_passed=True, maintain_default=False):
        """Download saved videos if video is enabled or if test fails

        :param name: destination file name
        :param test_passed: True if the test has passed
        :param maintain_default: True if the default driver should not be closed
        """
        # Exclude first wrapper if the driver must be reused
        driver_wrappers = cls.driver_wrappers[
            1:] if maintain_default else cls.driver_wrappers
        video_name = '{}_driver{}' if len(driver_wrappers) > 1 else '{}'
        video_name = video_name if test_passed else 'error_{}'.format(
            video_name)
        driver_index = 1

        for driver_wrapper in driver_wrappers:
            if not driver_wrapper.driver:
                continue
            try:
                # Download video if necessary (error case or enabled video)
                if (not test_passed or driver_wrapper.config.getboolean_optional('Server', 'video_enabled', False)) \
                        and driver_wrapper.remote_node_video_enabled:
                    if driver_wrapper.server_type in ['ggr', 'selenoid']:
                        name = get_valid_filename(
                            video_name.format(name, driver_index))
                        Selenoid(driver_wrapper).download_session_video(name)
                    elif driver_wrapper.server_type == 'grid':
                        # Download video from Grid Extras
                        driver_wrapper.utils.download_remote_video(
                            driver_wrapper.remote_node,
                            driver_wrapper.session_id,
                            video_name.format(name, driver_index))
            except Exception as exc:
                # Capture exceptions to avoid errors in teardown method due to session timeouts
                driver_wrapper.logger.warn('Error downloading videos: %s' %
                                           exc)
            driver_index += 1
    def save_all_ggr_logs(cls, test_name, test_passed):
        """Get all GGR logs of each driver and write them to log files

        :param test_name: test that has generated these logs
        :param test_passed: True if the test has passed
        """
        log_name = '{} [driver {}]' if len(cls.driver_wrappers) > 1 else '{}'
        driver_index = 1
        for driver_wrapper in cls.driver_wrappers:
            if not driver_wrapper.driver or driver_wrapper.server_type not in [
                    'ggr', 'selenoid'
            ]:
                continue
            try:
                if driver_wrapper.config.getboolean_optional(
                        'Server', 'logs_enabled') or not test_passed:
                    name = get_valid_filename(
                        log_name.format(test_name, driver_index))
                    Selenoid(driver_wrapper).download_session_log(name)
            except Exception as exc:
                # Capture exceptions to avoid errors in teardown method due to session timeouts
                driver_wrapper.logger.warn('Error downloading GGR logs: %s' %
                                           exc)
            driver_index += 1
Esempio n. 15
0
def test_get_valid_filename_length():
    input_filename = ' hola:pep /ito* '
    expected_filename = 'hola_pep__it'
    valid_filename = format_utils.get_valid_filename(input_filename, 12)

    assert expected_filename == valid_filename
Esempio n. 16
0
def test_get_valid_filename(input_filename, expected_filename):
    valid_filename = format_utils.get_valid_filename(input_filename)

    assert expected_filename == valid_filename
Esempio n. 17
0
def test_get_valid_filename_length():
    input_filename = ' hola:pep /ito* '
    expected_filename = 'hola_pep__it'
    valid_filename = format_utils.get_valid_filename(input_filename, 12)

    assert expected_filename == valid_filename
Esempio n. 18
0
def test_get_valid_filename(input_filename, expected_filename):
    valid_filename = format_utils.get_valid_filename(input_filename)

    assert expected_filename == valid_filename
Esempio n. 19
0
    def assert_screenshot(self,
                          element,
                          filename,
                          file_suffix=None,
                          threshold=0,
                          exclude_elements=[]):
        """Assert that a screenshot of an element is the same as a screenshot on disk, within a given threshold

        :param element: either a WebElement, PageElement or element locator as a tuple (locator_type, locator_value).
                        If None, a full screenshot is taken.
        :param filename: the filename for the screenshot, which will be appended with ``.png``
        :param file_suffix: a string to be appended to the output filename with extra info about the test.
        :param threshold: percentage threshold for triggering a test failure (value between 0 and 1)
        :param exclude_elements: list of WebElements, PageElements or element locators as a tuple (locator_type,
                                 locator_value) that must be excluded from the assertion
        """
        if not self.driver_wrapper.config.getboolean_optional(
                'VisualTests', 'enabled') and not self.force:
            return
        if not (isinstance(threshold, int) or isinstance(
                threshold, float)) or threshold < 0 or threshold > 1:
            raise TypeError(
                'Threshold must be a number between 0 and 1: {}'.format(
                    threshold))

        # Search elements
        web_element = self.utils.get_web_element(element)
        exclude_web_elements = []
        for exclude_element in exclude_elements:
            try:
                exclude_web_elements.append(
                    self.utils.get_web_element(exclude_element))
            except NoSuchElementException as e:
                self.logger.warning("Element to be excluded not found: %s",
                                    str(e))

        baseline_file = os.path.join(self.baseline_directory,
                                     '{}.png'.format(filename))
        filename_with_suffix = '{0}__{1}'.format(
            filename, file_suffix) if file_suffix else filename
        unique_name = '{0:0=2d}_{1}'.format(DriverWrappersPool.visual_number,
                                            filename_with_suffix)
        unique_name = '{}.png'.format(get_valid_filename(unique_name))
        output_file = os.path.join(self.output_directory, unique_name)
        report_name = '{}<br>({})'.format(
            file_suffix,
            filename) if file_suffix else '-<br>({})'.format(filename)

        # Get screenshot and modify it
        img = Image.open(
            BytesIO(self.driver_wrapper.driver.get_screenshot_as_png()))
        img = self.remove_scrolls(img)
        img = self.mobile_resize(img)
        img = self.exclude_elements(img, exclude_web_elements)
        img = self.crop_element(img, web_element)
        img.save(output_file)
        DriverWrappersPool.visual_number += 1

        # Determine whether we should save the baseline image
        if self.save_baseline or not os.path.exists(baseline_file):
            # Copy screenshot to baseline
            shutil.copyfile(output_file, baseline_file)

            if self.driver_wrapper.config.getboolean_optional(
                    'VisualTests', 'complete_report'):
                self._add_result_to_report('baseline', report_name,
                                           output_file, None,
                                           'Screenshot added to baseline')

            self.logger.debug(
                "Visual screenshot '%s' saved in visualtests/baseline folder",
                filename)
        else:
            # Compare the screenshots
            self.compare_files(report_name, output_file, baseline_file,
                               threshold)