OLD | NEW |
(Empty) | |
| 1 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 import json |
| 6 import logging |
| 7 import os |
| 8 import time |
| 9 from distutils.version import LooseVersion |
| 10 from PIL import Image |
| 11 |
| 12 from ..common import cloud_bucket |
| 13 from ..common import ispy_utils |
| 14 |
| 15 |
| 16 class ChromeUtils(object): |
| 17 """A utility for using ISpy with Chrome.""" |
| 18 |
| 19 def __init__(self, cloud_bucket, version_file, screenshot_func): |
| 20 """Initializes the utility class. |
| 21 |
| 22 Args: |
| 23 cloud_bucket: a BaseCloudBucket in which to the version file, |
| 24 expectations and results are to be stored. |
| 25 version_file: path to the version file in the cloud bucket. The version |
| 26 file contains a json list of ordered Chrome versions for which |
| 27 expectations exist. |
| 28 screenshot_func: a function that returns a PIL.Image. |
| 29 """ |
| 30 self._cloud_bucket = cloud_bucket |
| 31 self._version_file = version_file |
| 32 self._screenshot_func = screenshot_func |
| 33 self._ispy = ispy_utils.ISpyUtils(self._cloud_bucket) |
| 34 with open( |
| 35 os.path.join(os.path.dirname(__file__), 'wait_on_ajax.js'), 'r') as f: |
| 36 self._wait_for_unchanging_dom_script = f.read() |
| 37 |
| 38 def UpdateExpectationVersion(self, chrome_version): |
| 39 """Updates the most recent expectation version to the Chrome version. |
| 40 |
| 41 Should be called after generating a new set of expectations. |
| 42 |
| 43 Args: |
| 44 chrome_version: the chrome version as a string of the form "31.0.123.4". |
| 45 """ |
| 46 insert_pos = 0 |
| 47 expectation_versions = [] |
| 48 try: |
| 49 expectation_versions = self._GetExpectationVersionList() |
| 50 if expectation_versions: |
| 51 try: |
| 52 version = self._GetExpectationVersion( |
| 53 chrome_version, expectation_versions) |
| 54 if version == chrome_version: |
| 55 return |
| 56 insert_pos = expectation_versions.index(version) |
| 57 except: |
| 58 insert_pos = len(expectation_versions) |
| 59 except cloud_bucket.FileNotFoundError: |
| 60 pass |
| 61 expectation_versions.insert(insert_pos, chrome_version) |
| 62 logging.info('Updating expectation version...') |
| 63 self._cloud_bucket.UploadFile( |
| 64 self._version_file, json.dumps(expectation_versions), |
| 65 'application/json') |
| 66 |
| 67 def _GetExpectationVersion(self, chrome_version, expectation_versions): |
| 68 """Returns the expectation version for the given Chrome version. |
| 69 |
| 70 Args: |
| 71 chrome_version: the chrome version as a string of the form "31.0.123.4". |
| 72 expectation_versions: Ordered list of Chrome versions for which |
| 73 expectations exist, as stored in the version file. |
| 74 |
| 75 Returns: |
| 76 Expectation version string. |
| 77 """ |
| 78 # Find the closest version that is not greater than the chrome version. |
| 79 for version in expectation_versions: |
| 80 if LooseVersion(version) <= LooseVersion(chrome_version): |
| 81 return version |
| 82 raise Exception('No expectation exists for Chrome %s' % chrome_version) |
| 83 |
| 84 def _GetExpectationVersionList(self): |
| 85 """Gets the list of expectation versions from google storage.""" |
| 86 return json.loads(self._cloud_bucket.DownloadFile(self._version_file)) |
| 87 |
| 88 def _GetExpectationNameWithVersion(self, device_type, expectation, |
| 89 chrome_version): |
| 90 """Get the expectation to be used with the current Chrome version. |
| 91 |
| 92 Args: |
| 93 device_type: string identifier for the device type. |
| 94 expectation: name for the expectation to generate. |
| 95 chrome_version: the chrome version as a string of the form "31.0.123.4". |
| 96 |
| 97 Returns: |
| 98 Version as an integer. |
| 99 """ |
| 100 version = self._GetExpectationVersion( |
| 101 chrome_version, self._GetExpectationVersionList()) |
| 102 return self._CreateExpectationName(device_type, expectation, version) |
| 103 |
| 104 def _CreateExpectationName(self, device_type, expectation, version): |
| 105 """Create the full expectation name from the expectation and version. |
| 106 |
| 107 Args: |
| 108 device_type: string identifier for the device type, example: mako |
| 109 expectation: base name for the expectation, example: google.com |
| 110 version: expectation version, example: 31.0.23.1 |
| 111 |
| 112 Returns: |
| 113 Full expectation name as a string, example: mako:google.com(31.0.23.1) |
| 114 """ |
| 115 return '%s:%s(%s)' % (device_type, expectation, version) |
| 116 |
| 117 def GenerateExpectation(self, device_type, expectation, chrome_version): |
| 118 """Take screenshots and store as an expectation in I-Spy. |
| 119 |
| 120 Args: |
| 121 device_type: string identifier for the device type. |
| 122 expectation: name for the expectation to generate. |
| 123 chrome_version: the chrome version as a string of the form "31.0.123.4". |
| 124 """ |
| 125 # https://code.google.com/p/chromedriver/issues/detail?id=463 |
| 126 time.sleep(1) |
| 127 expectation_with_version = self._CreateExpectationName( |
| 128 device_type, expectation, chrome_version) |
| 129 if self._ispy.ExpectationExists(expectation_with_version): |
| 130 logging.warning( |
| 131 'I-Spy expectation \'%s\' already exists, overwriting.', |
| 132 expectation_with_version) |
| 133 screenshots = [self._screenshot_func() for _ in range(8)] |
| 134 logging.info('Generating I-Spy expectation...') |
| 135 self._ispy.GenerateExpectation(expectation_with_version, screenshots) |
| 136 |
| 137 def PerformComparison(self, test_run, device_type, expectation, |
| 138 chrome_version): |
| 139 """Take a screenshot and compare it with the given expectation in I-Spy. |
| 140 |
| 141 Args: |
| 142 test_run: name for the test run. |
| 143 device_type: string identifier for the device type. |
| 144 expectation: name for the expectation to compare against. |
| 145 chrome_version: the chrome version as a string of the form "31.0.123.4". |
| 146 """ |
| 147 # https://code.google.com/p/chromedriver/issues/detail?id=463 |
| 148 time.sleep(1) |
| 149 screenshot = self._screenshot_func() |
| 150 logging.info('Performing I-Spy comparison...') |
| 151 self._ispy.PerformComparison( |
| 152 test_run, |
| 153 self._GetExpectationNameWithVersion( |
| 154 device_type, expectation, chrome_version), |
| 155 screenshot) |
| 156 |
| 157 def WaitForUnchangingDOM(self, driver): |
| 158 """Waits for the DOM to stop changing. |
| 159 |
| 160 Args: |
| 161 driver: a chromedriver driver instance. |
| 162 """ |
| 163 try: |
| 164 driver.execute_async_script(self._wait_for_unchanging_dom_script) |
| 165 except exceptions.TimeoutException: |
| 166 logging.warning('Timed out waiting for DOM to stop changing') |
| 167 |
OLD | NEW |