Project

General

Profile

Revision 544:e6f81d7c26db

Added by Daniel Havlik almost 8 years ago

re #12065 refactor screenshot assertion

View differences:

src/gocept/selenium/screenshot.py
27 27
        self.width = self.exp.size[0]
28 28
        self.height = self.exp.size[1]
29 29
        self.prepare_composition()
30
        self.paste_screenshots()
31
        ignored, compo_path = tempfile.mkstemp('.png')
32
        with open(compo_path, 'rw') as compo:
33
            self.path = compo.name
34
            self.compo.save(self.path)
35
            if SHOW_DIFF_IMG:
36
                self.compo.show()
30 37

  
31 38
    def prepare_composition(self):
32 39
        """prepares and returns the composition image, given width
......
43 50
            pos = (5, index*(self.height+self.label_margin))
44 51
            self.compo.paste(img, pos)
45 52

  
46

  
47 53
    def paste_screenshots(self):
48 54
        for index, screenshot in enumerate((self.exp, self.got, self.diff)):
49 55
            pos = (0, (index*self.height)+((index+1)*self.label_margin))
50 56
            self.compo.paste(screenshot, pos)
51 57

  
52 58
    @property
53
    def composition(self):
54
        self.paste_screenshots()
55
        return self.compo
56

  
57
    @property
58 59
    def diff(self):
59 60
        def subtract(source, sub):
60 61
            return ImageChops.invert(
......
87 88
    def __init__(self, image_a, image_b):
88 89
        self.image_a = image_a
89 90
        self.image_b = image_b
91
        self.distance = self.get_nrmsd() * 100
92

  
93
    def within_threshold(self, threshold):
94
        return self.distance < threshold
90 95

  
91 96
    def get_nrmsd(self):
92 97
        """
......
98 103
        for a, b in itertools.izip(a_values, b_values):
99 104
            rmsd += (a - b) ** 2
100 105
        rmsd = math.sqrt(float(rmsd) / (
101
            self.image_a.size[0] * self.image_a.size[1] * len(self.image_a.getbands())
106
            self.image_a.size[0] * self.image_a.size[1] * len(
107
                self.image_a.getbands())
102 108
        ))
103 109
        return rmsd / 255
104 110

  
......
142 148
                               self.expected, self.got)
143 149

  
144 150

  
145
def _get_screenshot(selenese, locator):
151
def make_screenshot(selenese, locator):
146 152
    ignored, path = tempfile.mkstemp()
147 153
    selenese.captureScreenshot(path)
148 154

  
......
176 182
            screenshot_directory, '')
177 183

  
178 184

  
179
def assertScreenshot(selenese, name, locator, threshold=1):
180
    filename = os.path.join(
181
        _screenshot_path(selenese.screenshot_directory), '%s.png' % name)
182
    screenshot = _get_screenshot(selenese, locator)
185
def save_screenshot_temporary(screenshot):
186
    """Saves given screenshot to a temporary file and return
187
    the filename."""
188
    ignored, got_path = tempfile.mkstemp('.png')
189
    with open(got_path, 'rw') as got:
190
        screenshot.save(got.name)
191
    return got.name
192

  
193

  
194
def save_as_expected(screenshot, img_basename, exp_path):
195
    if os.path.exists(exp_path):
196
        raise ValueError(
197
            'Not capturing {}, image already exists. If you '
198
            'want to capture this element again, delete {}'.format(
199
                img_basename, exp_path))
200
    screenshot.save(exp_path)
201
    raise ValueError(
202
        'Captured {}. You might now want to remove capture mode and '
203
        'check in the created screenshot {}.'.format(
204
            img_basename, exp_path))
205

  
206

  
207
def assertScreenshot(selenese, img_basename, locator, threshold=1):
208
    exp_path = os.path.join(
209
        _screenshot_path(selenese.screenshot_directory), '%s.png' % img_basename)
210
    screenshot = make_screenshot(selenese, locator)
183 211
    if selenese.capture_screenshot:
184
        if os.path.exists(filename):
185
            raise ValueError(
186
                'Not capturing {}, image already exists. If you '
187
                'want to capture this element again, delete {}'.format(
188
                    name, filename))
189
        screenshot.save(filename)
190
        raise ValueError(
191
            'Captured {}. You might now want to remove capture mode and '
192
            'check in the created screenshot {}.'.format(name, filename))
212
        #In capture mode, we only want to save the screenshot
213
        #as the new expected image.
214
        save_as_expected(screenshot, img_basename, exp_path)
193 215
        return
194
    image = Image.open(filename)
195
    diff = ImageDiff(screenshot, image)
196
    distance = abs(diff.get_nrmsd()) * 100
197
    if distance > threshold:
198
        ignored, got_path = tempfile.mkstemp('.png')
199
        with open(got_path, 'rw') as got:
200
            screenshot.save(got.name)
201
        if image.size != screenshot.size:
216
    exp = Image.open(exp_path)
217
    diff = ImageDiff(screenshot, exp)
218
    if not diff.within_threshold(threshold):
219
        #In failure case, we save the screenshot.
220
        got_path = save_screenshot_temporary(screenshot)
221
        if exp.size != screenshot.size:
222
            #Seperate exception if sizes differ.
202 223
            raise ScreenshotSizeMismatchError(
203
                name, image.size, screenshot.size, filename, got.name)
204
            return
205
        ignored, compo_path = tempfile.mkstemp('.png')
206
        with open(compo_path, 'rw') as compo:
207
            compo_img = DiffComposition(image, screenshot).composition
208
            compo_img.save(compo.name)
209
            if SHOW_DIFF_IMG:
210
                compo_img.show()
224
                img_basename, exp.size, screenshot.size, exp_path, got_path)
225
        #Sizes are the same, so we can render a nice diff image.
226
        compo = DiffComposition(exp, screenshot)
211 227
        raise ScreenshotMismatchError(
212
            name, distance, filename, got.name, compo.name)
228
            img_basename, diff.distance, exp_path, got_path, compo.path)
213 229

  
230

  

Also available in: Unified diff