def compareScreenshot(self, element_or_selector, filename, threshold=0.1): """ 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.NeedleWebElement` object that represents the element to capture. :param name: A name for the screenshot, which will be appended with ``.png``. :param threshold: The threshold for triggering a test failure. """ if not isinstance(filename, basestring): raise NotImplementedError baseline_file = os.path.join(self.baseline_directory, '%s.png' % filename) output_file = os.path.join(self.output_directory, '%s.png' % filename) if self.capture and os.path.exists(baseline_file): self.skipTest('Not capturing %s, image already exists. If you ' 'want to capture this element again, delete %s' % (filename, baseline_file)) yield if not isinstance(element_or_selector, NeedleWebElement): element = self.driver.find_element_by_css_selector(element_or_selector) else: element = element_or_selector if self.capture: element.get_screenshot().save(baseline_file) return else: screenshot = element.get_screenshot() screenshot.save(output_file) if self.use_perceptualdiff: diff_filename = output_file.replace(".png", ".diff.ppm") try: # BUG: figure out how best to convert threshold distances to pixel counts subprocess.check_call(["perceptualdiff", "-output", diff_filename, baseline_file, output_file]) except subprocess.CalledProcessError: raise AssertionError("The saved screenshot for '%s' did not match " "the screenshot captured: see %s" % (filename, diff_filename)) else: baseline_image = Image.open(baseline_file) diff = ImageDiff(screenshot, baseline_image) distance = abs(diff.get_distance()) if distance > threshold: raise AssertionError("The saved screenshot for '%s' did not match " "the screenshot captured (by a distance of %.2f)" % (filename, distance))
def assertScreenshot(self, element, name, threshold=0.1): """ Assert that a screenshot of an element is the same as a screenshot on disk, within a given threshold. :param element: Either a CSS selector as a string or a :py:class:`~needle.driver.NeedleWebElement` object that represents the element to capture. :param name: A name for the screenshot, which will be appended with ``.png``. :param threshold: The threshold for triggering a test failure. """ if isinstance(element, basestring): element = self.driver.find_element_by_css_selector(element) if isinstance(name, basestring): filename = os.path.join( os.path.dirname(_object_filename(self)), '%s.png' % name ) else: # names can be filehandles for testing. This sucks - we # should write out files to their correct location filename = name if self.capture: if os.path.exists(filename): self.skipTest('Not capturing %s, image already exists. If you ' 'want to capture this element again, delete %s' % (name, filename)) element.get_screenshot().save(filename) else: image = Image.open(filename) # now take another screenshot and re open it (yea i know) but there were issues wth colours screenshot_filename = filename.replace('.png','-compare.png') screenshot = element.get_screenshot().save(screenshot_filename) screenshot = Image.open(screenshot_filename) diff = ImageDiff(screenshot, image) distance = abs(diff.get_distance()) if distance > threshold: raise AssertionError("The saved screenshot for '%s' did not match " "the screenshot captured (by a distance of %.2f)" % (name, distance))
def test_nrmsd_all_channels(self): diff = ImageDiff(self.get_white_image(), self.get_black_image()) self.assertEqual(diff.get_nrmsd(), 1)
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)
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)
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)
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))
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))
def compareScreenshot(self, element_or_selector, filename, threshold=0.1): """ 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.NeedleWebElement` object that represents the element to capture. :param name: A name for the screenshot, which will be appended with ``.png``. :param threshold: The threshold for triggering a test failure. """ if not isinstance(filename, basestring): raise NotImplementedError baseline_file = os.path.join(self.baseline_directory, '%s.png' % filename) output_file = os.path.join(self.output_directory, '%s.png' % filename) if self.capture and os.path.exists(baseline_file): self.skipTest('Not capturing %s, image already exists. If you ' 'want to capture this element again, delete %s' % (filename, baseline_file)) yield if not isinstance(element_or_selector, NeedleWebElement): element = self.driver.find_element_by_css_selector( element_or_selector) else: element = element_or_selector if self.capture: element.get_screenshot().save(baseline_file) return else: screenshot = element.get_screenshot() screenshot.save(output_file) if self.use_perceptualdiff: diff_filename = output_file.replace(".png", ".diff.ppm") try: # BUG: figure out how best to convert threshold distances to pixel counts subprocess.check_call([ "perceptualdiff", "-output", diff_filename, baseline_file, output_file ]) except subprocess.CalledProcessError: raise AssertionError( "The saved screenshot for '%s' did not match " "the screenshot captured: see %s" % (filename, diff_filename)) else: baseline_image = Image.open(baseline_file) diff = ImageDiff(screenshot, baseline_image) distance = abs(diff.get_distance()) if distance > threshold: raise AssertionError( "The saved screenshot for '%s' did not match " "the screenshot captured (by a distance of %.2f)" % (filename, distance))
def compareScreenshot(self, element_or_selector, file, threshold=0.1): """ 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.NeedleWebElement` 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, NeedleWebElement): element = self.driver.find_element_by_css_selector(element_or_selector) else: element = element_or_selector if isinstance(file, basestring): baseline_file = os.path.join(self.baseline_directory, '%s.png' % file) output_file = os.path.join(self.output_directory, '%s.png' % file) if self.capture and os.path.exists(baseline_file): self.skipTest('Not capturing %s, image already exists. If you ' 'want to capture this element again, delete %s' % (file, baseline_file)) if self.capture: element.get_screenshot().save(baseline_file) return else: baseline_image = Image.open(baseline_file) fresh_screenshot = element.get_screenshot() fresh_screenshot.save(output_file) if self.use_perceptualdiff: # TODO: figure out how best to convert threshold distances to pixel counts diff_ppm = output_file.replace(".png", ".diff.ppm") cmd = "%s -output %s %s %s" % (self.perceptualdiff_path, diff_ppm, baseline_file, output_file) process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) perceptualdiff_stdout, _ = process.communicate() if process.returncode == 0: # No differences found return else: if os.path.exists(diff_ppm): if self.perceptualdiff_output_png: # Convert the .ppm output to .png diff_png = diff_ppm.replace("diff.ppm", "diff.png") Image.open(diff_ppm).save(diff_png) os.remove(diff_ppm) diff_file_msg = ' (See %s)' % diff_png else: diff_file_msg = ' (See %s)' % diff_ppm else: diff_file_msg = '' raise AssertionError("The saved screenshot for '%s' did not match " "the screenshot captured%s:\n%s" % (file, diff_file_msg, perceptualdiff_stdout)) else: 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 given screenshot did not match the " "screenshot captured (by a distance of %.2f)" % distance)