Beispiel #1
0
    def assertScreenshot(self, selector, path):
        """
        Assert that the element as defined by the passed CSS `selector` is
        the same as the one saved in the baseline screenshot.

        Note that this method will generate a baseline screenshot if the
        make_baseline_screenshots config option is set to true. No assertions
        will occur.

        :param unicode selector: CSS selector of element to screenshot.
        :param path: URL path to page where element is found.
        """
        for display_name, browser_name, driver in self._yield_drivers():
            url = self._make_url(path)
            driver.get(url)

            # selenium checks for a str instance. Unicode would fail here.
            element = driver.find_element_by_css_selector(str(selector))
            sleep(1)
            screenshot = element.get_screenshot()

            baseline_path = self._make_screenshot_path(
                self._BASELINE_FOLDER_NAME, browser_name, display_name)

            baseline_file = '{}/{}--{}.png'.format(baseline_path, path,
                                                   selector)
            # Create the directory if it does not exist.
            if not os.path.exists(baseline_path):
                os.makedirs(baseline_path)

            if self._make_baseline_screenshots:
                screenshot.save(baseline_file)
                log.warning(
                    'Creating baseline screenshot: {}'.format(baseline_file))
            else:
                try:
                    baseline_screenshot = Image.open(baseline_file).convert(
                        'RGB')
                except IOError:
                    raise MissingBaselineScreenshotException

                error_path = self._make_screenshot_path(
                    self._ERROR_FOLDER_NAME, browser_name, display_name)

                if not os.path.exists(error_path):
                    os.makedirs(error_path)

                error_file = '{}/{}--{}.png'.format(error_path, path, selector)
                try:
                    diff = ImageDiff(screenshot, baseline_screenshot)
                except AssertionError:
                    screenshot.save(error_file)
                    raise AssertScreenshotException(error_file)

                distance = abs(diff.get_distance())
                if distance > self._THRESHOLD:
                    screenshot.save(error_file)
                    raise AssertScreenshotException(distance)
            driver.close()
Beispiel #2
0
 def assertSameFiles(self, output_file, baseline_file, threshold):
     output_image = Image.open(output_file).convert('RGB')
     baseline_image = Image.open(baseline_file).convert('RGB')
     diff = ImageDiff(output_image, baseline_image)
     distance = abs(diff.get_distance())
     if distance > threshold:
         raise AssertionError("The new screenshot '%s' did not match "
                              "the baseline '%s' (by a distance of %.2f)" %
                              (output_file, baseline_file, distance))
Beispiel #3
0
 def assertSameFiles(self, output_file, baseline_file, threshold):
     output_image = Image.open(output_file).convert('RGB')
     baseline_image = Image.open(baseline_file).convert('RGB')
     diff = ImageDiff(output_image, baseline_image)
     distance = abs(diff.get_distance())
     if distance > threshold:
         raise AssertionError("The new screenshot '%s' did not match "
                              "the baseline '%s' (by a distance of %.2f)"
                              % (output_file, baseline_file, distance))
Beispiel #4
0
 def test_distance_all_channels(self):
     diff = ImageDiff(self.get_white_image(), self.get_black_image())
     self.assertAlmostEqual(diff.get_distance(), 100 * 100, delta=0.001)
Beispiel #5
0
 def test_nrmsd_half_filled(self):
     diff = ImageDiff(self.get_black_image(), self.get_half_filled_image())
     self.assertEqual(diff.get_nrmsd(), math.sqrt(0.5))
Beispiel #6
0
 def test_nrmsd_one_channel(self):
     diff = ImageDiff(self.get_image((255, 0, 0)), self.get_black_image())
     self.assertEqual(diff.get_nrmsd(), math.sqrt(1.0 / 3))
Beispiel #7
0
 def test_nrmsd_all_channels(self):
     diff = ImageDiff(self.get_white_image(), self.get_black_image())
     self.assertEqual(diff.get_nrmsd(), 1)
Beispiel #8
0
 def test_distance_half_filled(self):
     diff = ImageDiff(self.get_black_image(), self.get_half_filled_image())
     self.assertAlmostEqual(diff.get_distance(), 10000.0 / 2, delta=0.001)
Beispiel #9
0
    def assertScreenshot(self, selector, path):
        """
        Assert that the element as defined by the passed CSS `selector` is
        the same as the one saved in the baseline screenshot.

        Note that this method will generate a baseline screenshot if the
        make_baseline_screenshots config option is set to true. No assertions
        will occur.

        :param unicode selector: CSS selector of element to screenshot.
        :param path: URL path to page where element is found.
        """
        for display_name, browser_name, driver in self._yield_drivers():
            url = self._make_url(path)
            driver.get(url)

            # selenium checks for a str instance. Unicode would fail here.
            element = driver.find_element_by_css_selector(str(selector))
            sleep(1)
            screenshot = element.get_screenshot()

            baseline_path = self._make_screenshot_path(
                self._BASELINE_FOLDER_NAME,
                browser_name,
                display_name)

            baseline_file = '{}/{}--{}.png'.format(
                baseline_path,
                path,
                selector)
            # Create the directory if it does not exist.
            if not os.path.exists(baseline_path):
                os.makedirs(baseline_path)

            if self._make_baseline_screenshots:
                screenshot.save(baseline_file)
                log.warning('Creating baseline screenshot: {}'.format(
                    baseline_file))
            else:
                try:
                    baseline_screenshot = Image.open(baseline_file).convert('RGB')
                except IOError:
                    raise MissingBaselineScreenshotException

                error_path = self._make_screenshot_path(
                    self._ERROR_FOLDER_NAME,
                    browser_name,
                    display_name)

                if not os.path.exists(error_path):
                    os.makedirs(error_path)

                error_file = '{}/{}--{}.png'.format(
                    error_path,
                    path,
                    selector)
                try:
                    diff = ImageDiff(screenshot, baseline_screenshot)
                except AssertionError:
                    screenshot.save(error_file)
                    raise AssertScreenshotException(error_file)

                distance = abs(diff.get_distance())
                if distance > self._THRESHOLD:
                    screenshot.save(error_file)
                    raise AssertScreenshotException(distance)
            driver.close()
Beispiel #10
0
    def compareScreenshot(self, element_or_selector, file, threshold=0):
        """
        Assert that a screenshot of an element is the same as a screenshot on disk,
        within a given threshold.

        :param element_or_selector:
            Either a CSS selector as a string or a
            :py:class:`~needle.driver.NeedleWebElementMixin` object that represents
            the element to capture.
        :param file:
            If a string, then assumed to be the filename for the screenshot,
            which will be appended with ``.png``. Otherwise assumed to be
            a file object for the baseline image.
        :param threshold:
            The threshold for triggering a test failure.
        """

        yield  # To allow using this method as a context manager

        if not isinstance(element_or_selector, NeedleWebElementMixin):
            element = self.driver.find_element_by_css_selector(
                element_or_selector)
        else:
            element = element_or_selector

        if not isinstance(file, basestring):
            # Comparing in-memory files instead of on-disk files
            baseline_image = Image.open(file).convert('RGB')
            fresh_screenshot = element.get_screenshot()
            diff = ImageDiff(fresh_screenshot, baseline_image)
            distance = abs(diff.get_distance())
            if distance > threshold:
                raise AssertionError("The new screenshot did not match "
                                     "the baseline (by a distance of %.2f)" %
                                     distance)
        else:
            baseline_file = os.path.join(self.baseline_directory,
                                         '%s.png' % file)
            output_file = os.path.join(self.output_directory, '%s.png' % file)

            # Determine whether we should save the baseline image
            save_baseline = False
            if self.save_baseline:
                save_baseline = True
            elif self.capture:
                warn(
                    "The 'NeedleTestCase.capture' attribute and '--with-save-baseline' nose option "
                    "are deprecated since version 0.2.0. Use 'save_baseline' and '--with-save-baseline' "
                    "instead. See the changelog for more information.",
                    PendingDeprecationWarning)
                if os.path.exists(baseline_file):
                    self.skipTest(
                        'Not capturing %s, its baseline image already exists. If you '
                        'want to capture this element again, delete %s' %
                        (file, baseline_file))
                else:
                    save_baseline = True

            if save_baseline:
                # Save the baseline screenshot and bail out
                element.get_screenshot().save(baseline_file)
                return
            else:
                if not os.path.exists(baseline_file):
                    raise IOError(
                        'The baseline screenshot %s does not exist. '
                        'You might want to re-run this test in baseline-saving mode.'
                        % baseline_file)

                # Save the new screenshot
                element.get_screenshot().save(output_file)

                try:
                    self.engine.assertSameFiles(output_file, baseline_file,
                                                threshold)
                except:
                    raise
                else:
                    if self.cleanup_on_success:
                        os.remove(output_file)
Beispiel #11
0
 def test_nrmsd_half_filled(self):
     diff = ImageDiff(self.get_black_image(), self.get_half_filled_image())
     self.assertEqual(diff.get_nrmsd(), math.sqrt(0.5))
Beispiel #12
0
 def test_nrmsd_one_channel(self):
     diff = ImageDiff(self.get_image((255, 0, 0)), self.get_black_image())
     self.assertEqual(diff.get_nrmsd(), math.sqrt(1.0 / 3))
Beispiel #13
0
 def test_nrmsd_all_channels(self):
     diff = ImageDiff(self.get_white_image(), self.get_black_image())
     self.assertEqual(diff.get_nrmsd(), 1)
Beispiel #14
0
    def assert_screenshot(self,
                          file_path,
                          element_or_selector=None,
                          threshold=0,
                          exclude=None):
        """Fail if new fresh image is too dissimilar from the baseline image

        .. note:: From needle
            https://github.com/python-needle/needle/blob/master/needle/cases.py#L161

        :param str file_path: File name for baseline image
        :param element_or_selector: WebElement or tuple containing selector ex. ('id', 'mainPage')
        :param threshold: Distance threshold
        :param list exclude: Elements or element selectors for areas to exclude
        :return:
        """

        element = self._find_element(
            element_or_selector) if element_or_selector else None

        # Get baseline screenshot
        self._create_dir(self.baseline_dir)
        baseline_image = os.path.join(self.baseline_dir, '%s.png' % file_path) \
            if isinstance(file_path, basestring) else Image.open(file_path).convert('RGB')

        # Take screenshot and exit if in baseline saving mode
        if self.save_baseline:
            self.get_screenshot_as_image(element,
                                         exclude=exclude).save(baseline_image)
            return

        # Get fresh screenshot
        self._create_dir(self.output_dir)
        fresh_image = self.get_screenshot_as_image(element, exclude=exclude)
        fresh_image_file = os.path.join(self.output_dir, '%s.png' % file_path)
        fresh_image.save(fresh_image_file)

        # Error if there is not a baseline image to compare
        if not self.save_baseline and not isinstance(
                file_path, basestring) and not os.path.exists(baseline_image):
            raise IOError(
                'The baseline screenshot %s does not exist. You might want to '
                're-run this test in baseline-saving mode.' % baseline_image)

        # Compare images
        if isinstance(baseline_image, basestring):
            try:
                self.engine.assertSameFiles(fresh_image_file, baseline_image,
                                            threshold)

            except AssertionError as err:
                msg = getattr(err, 'message', err.args[0] if err.args else "")
                args = err.args[1:] if len(err.args) > 1 else []
                raise ImageMismatchException(msg, baseline_image,
                                             fresh_image_file, args)

            except EnvironmentError:
                msg = "Missing baseline '{}'. Please run again with --needle-save-baseline".format(
                    baseline_image)
                raise MissingBaselineException(msg)

            except ValueError as err:

                if self.options['needle_engine'] == 'imagemagick':
                    msg = "It appears {0} is not installed. Please verify {0} is installed or choose a different engine"
                    raise MissingEngineException(
                        msg.format(self.options['needle_engine']))

                raise err

            finally:
                if self.cleanup_on_success:
                    os.remove(fresh_image_file)

        else:

            diff = ImageDiff(fresh_image, baseline_image)
            distance = abs(diff.get_distance())

            if distance > threshold:
                pytest.fail(
                    'Fail: New screenshot did not match the baseline (by a distance of %.2f)'
                    % distance)
Beispiel #15
0
 def test_distance_one_channel(self):
     diff = ImageDiff(self.get_image((255, 0, 0)), self.get_black_image())
     self.assertAlmostEqual(diff.get_distance(), 10000.0 / 3, delta=0.001)
Beispiel #16
0
 def test_distance_all_channels(self):
     diff = ImageDiff(self.get_white_image(), self.get_black_image())
     self.assertAlmostEqual(diff.get_distance(), 100 * 100, delta=0.001)
Beispiel #17
0
 def test_distance_half_filled(self):
     diff = ImageDiff(self.get_black_image(), self.get_half_filled_image())
     self.assertAlmostEqual(diff.get_distance(), 10000.0 / 2, delta=0.001)
Beispiel #18
0
 def test_distance_one_channel(self):
     diff = ImageDiff(self.get_image((255, 0, 0)), self.get_black_image())
     self.assertAlmostEqual(diff.get_distance(), 10000.0 / 3, delta=0.001)
Beispiel #19
0
    def compareScreenshot(self, element_or_selector, file, threshold=0):
        """
        Assert that a screenshot of an element is the same as a screenshot on disk,
        within a given threshold.

        :param element_or_selector:
            Either a CSS selector as a string or a
            :py:class:`~needle.driver.NeedleWebElementMixin` object that represents
            the element to capture.
        :param file:
            If a string, then assumed to be the filename for the screenshot,
            which will be appended with ``.png``. Otherwise assumed to be
            a file object for the baseline image.
        :param threshold:
            The threshold for triggering a test failure.
        """

        yield  # To allow using this method as a context manager

        if not isinstance(element_or_selector, NeedleWebElementMixin):
            element = self.driver.find_element_by_css_selector(element_or_selector)
        else:
            element = element_or_selector

        if not isinstance(file, basestring):
            # Comparing in-memory files instead of on-disk files
            baseline_image = Image.open(file).convert('RGB')
            fresh_screenshot = element.get_screenshot()
            diff = ImageDiff(fresh_screenshot, baseline_image)
            distance = abs(diff.get_distance())
            if distance > threshold:
                raise AssertionError("The new screenshot did not match "
                                     "the baseline (by a distance of %.2f)"
                                     % distance)
        else:
            baseline_file = os.path.join(self.baseline_directory, '%s.png' % file)
            output_file = os.path.join(self.output_directory, '%s.png' % file)

            # Determine whether we should save the baseline image
            save_baseline = False
            if self.save_baseline:
                save_baseline = True
            elif self.capture:
                warn("The 'NeedleTestCase.capture' attribute and '--with-save-baseline' nose option "
                     "are deprecated since version 0.2.0. Use 'save_baseline' and '--with-save-baseline' "
                     "instead. See the changelog for more information.",
                     PendingDeprecationWarning)
                if os.path.exists(baseline_file):
                    self.skipTest('Not capturing %s, its baseline image already exists. If you '
                                  'want to capture this element again, delete %s'
                                  % (file, baseline_file))
                else:
                    save_baseline = True

            if save_baseline:
                # Save the baseline screenshot and bail out
                element.get_screenshot().save(baseline_file)
                return
            else:
                if not os.path.exists(baseline_file):
                    raise IOError('The baseline screenshot %s does not exist. '
                                  'You might want to re-run this test in baseline-saving mode.'
                                  % baseline_file)

                # Save the new screenshot
                element.get_screenshot().save(output_file)

                try:
                    self.engine.assertSameFiles(output_file, baseline_file, threshold)
                except:
                    raise
                else:
                    if self.cleanup_on_success:
                        os.remove(output_file)
Beispiel #20
0
    def assert_screenshot(self,
                          file_path,
                          element_or_selector=None,
                          threshold=0,
                          exclude=None):
        """Fail if new fresh image is too dissimilar from the baseline image

        .. note:: From needle
            https://github.com/python-needle/needle/blob/master/needle/cases.py#L161

        :param str file_path: File name for baseline image
        :param element_or_selector: WebElement or tuple containing selector ex. ('id', 'mainPage')
        :param threshold: Distance threshold
        :param list exclude: Elements or element selectors for areas to exclude
        :return:
        """

        element = self._find_element(element_or_selector)

        # Get baseline image
        if isinstance(file_path, basestring):

            baseline_image = os.path.join(self.baseline_dir,
                                          '%s.png' % file_path)

            if self.save_baseline:

                # Take screenshot and exit
                return self.get_screenshot_as_image(
                    element, exclude=exclude).save(baseline_image)

            else:

                if not os.path.exists(baseline_image):
                    raise IOError(
                        'The baseline screenshot %s does not exist. '
                        'You might want to re-run this test in baseline-saving mode.'
                        % baseline_image)

        else:

            # Comparing in-memory files instead of on-disk files
            baseline_image = Image.open(file_path).convert('RGB')

        # Get fresh screenshot
        fresh_image = self.get_screenshot_as_image(element, exclude=exclude)

        # Compare images
        if isinstance(baseline_image, basestring):

            output_file = os.path.join(self.output_dir, '%s.png' % file_path)
            fresh_image.save(output_file)

            try:
                self.engine.assertSameFiles(output_file, baseline_image,
                                            threshold)

            except AssertionError as err:
                msg = err.message \
                    if hasattr(err, "message") \
                    else err.args[0] if err.args else ""
                args = err.args[1:] if len(err.args) > 1 else []
                raise ImageMismatchException(msg, baseline_image, output_file,
                                             args)

            finally:
                if self.cleanup_on_success:
                    os.remove(output_file)

        else:

            diff = ImageDiff(fresh_image, baseline_image)
            distance = abs(diff.get_distance())

            if distance > threshold:
                pytest.fail('Fail: New screenshot did not match the '
                            'baseline (by a distance of %.2f)' % distance)