| OLD | NEW |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """The testing Environment class.""" | 5 """The testing Environment class. |
| 6 |
| 7 It holds the WebsiteTest instances, provides them with credentials, |
| 8 provides clean browser environment, runs the tests, and gathers the |
| 9 results. |
| 10 """ |
| 6 | 11 |
| 7 import os | 12 import os |
| 8 import shutil | 13 import shutil |
| 9 import time | 14 import time |
| 10 from xml.etree import ElementTree | 15 from xml.etree import ElementTree |
| 11 | 16 |
| 12 from selenium import webdriver | 17 from selenium import webdriver |
| 13 from selenium.webdriver.chrome.options import Options | 18 from selenium.webdriver.chrome.options import Options |
| 14 | 19 |
| 15 | 20 |
| 16 # Message strings to look for in chrome://password-manager-internals | 21 # Message strings to look for in chrome://password-manager-internals. |
| 17 MESSAGE_ASK = "Message: Decision: ASK the user" | 22 MESSAGE_ASK = "Message: Decision: ASK the user" |
| 18 MESSAGE_SAVE = "Message: Decision: SAVE the password" | 23 MESSAGE_SAVE = "Message: Decision: SAVE the password" |
| 19 | 24 |
| 20 | 25 INTERNALS_PAGE_URL = "chrome://password-manager-internals/" |
| 21 class TestResult: | |
| 22 """Stores the information related to a test result. """ | |
| 23 def __init__(self, name, test_type, successful, message): | |
| 24 """Creates a new TestResult. | |
| 25 | |
| 26 Args: | |
| 27 name: The tested website name. | |
| 28 test_type: The test type. | |
| 29 successful: Whether or not the test was successful. | |
| 30 message: The error message of the test. | |
| 31 """ | |
| 32 self.name = name | |
| 33 self.test_type = test_type | |
| 34 self.successful = successful | |
| 35 self.message = message | |
| 36 | |
| 37 | 26 |
| 38 class Environment: | 27 class Environment: |
| 39 """Sets up the testing Environment. """ | 28 """Sets up the testing Environment. """ |
| 40 | 29 |
| 41 def __init__(self, chrome_path, chromedriver_path, profile_path, | 30 def __init__(self, chrome_path, chromedriver_path, profile_path, |
| 42 passwords_path, enable_automatic_password_saving): | 31 passwords_path, enable_automatic_password_saving): |
| 43 """Creates a new testing Environment. | 32 """Creates a new testing Environment, starts Chromedriver. |
| 44 | 33 |
| 45 Args: | 34 Args: |
| 46 chrome_path: The chrome binary file. | 35 chrome_path: The chrome binary file. |
| 47 chromedriver_path: The chromedriver binary file. | 36 chromedriver_path: The chromedriver binary file. |
| 48 profile_path: The chrome testing profile folder. | 37 profile_path: The chrome testing profile folder. |
| 49 passwords_path: The usernames and passwords file. | 38 passwords_path: The usernames and passwords file. |
| 50 enable_automatic_password_saving: If True, the passwords are going to be | 39 enable_automatic_password_saving: If True, the passwords are going to be |
| 51 saved without showing the prompt. | 40 saved without showing the prompt. |
| 52 | 41 |
| 53 Raises: | 42 Raises: |
| 43 IOError: When the passwords file cannot be accessed. |
| 44 ParseError: When the passwords file cannot be parsed. |
| 54 Exception: An exception is raised if |profile_path| folder could not be | 45 Exception: An exception is raised if |profile_path| folder could not be |
| 55 removed. | 46 removed. |
| 56 """ | 47 """ |
| 57 | 48 |
| 58 # Cleaning the chrome testing profile folder. | 49 # Cleaning the chrome testing profile folder. |
| 59 if os.path.exists(profile_path): | 50 if os.path.exists(profile_path): |
| 60 shutil.rmtree(profile_path) | 51 shutil.rmtree(profile_path) |
| 52 |
| 61 options = Options() | 53 options = Options() |
| 62 self.enable_automatic_password_saving = enable_automatic_password_saving | |
| 63 if enable_automatic_password_saving: | 54 if enable_automatic_password_saving: |
| 64 options.add_argument("enable-automatic-password-saving") | 55 options.add_argument("enable-automatic-password-saving") |
| 65 # Chrome path. | 56 # TODO(vabr): show_prompt is used in WebsiteTest for asserting that |
| 57 # Chrome set-up corresponds to the test type. Remove that knowledge |
| 58 # about Environment from the WebsiteTest. |
| 59 self.show_prompt = not enable_automatic_password_saving |
| 66 options.binary_location = chrome_path | 60 options.binary_location = chrome_path |
| 67 # Chrome testing profile path. | |
| 68 options.add_argument("user-data-dir=%s" % profile_path) | 61 options.add_argument("user-data-dir=%s" % profile_path) |
| 69 | 62 |
| 70 # The webdriver. It's possible to choose the port the service is going to | 63 # The webdriver. It's possible to choose the port the service is going to |
| 71 # run on. If it's left to 0, a free port will be found. | 64 # run on. If it's left to 0, a free port will be found. |
| 72 self.driver = webdriver.Chrome(chromedriver_path, 0, options) | 65 self.driver = webdriver.Chrome(chromedriver_path, 0, options) |
| 73 # The password internals window. | 66 |
| 67 # Password internals page tab/window handle. |
| 74 self.internals_window = self.driver.current_window_handle | 68 self.internals_window = self.driver.current_window_handle |
| 75 if passwords_path: | 69 |
| 76 # An xml tree filled with logins and passwords. | 70 # An xml tree filled with logins and passwords. |
| 77 self.passwords_tree = ElementTree.parse(passwords_path).getroot() | 71 self.passwords_tree = ElementTree.parse(passwords_path).getroot() |
| 78 else: | 72 |
| 79 raise Exception("Error: |passwords_path| needs to be provided if" | 73 self.website_window = self._OpenNewTab() |
| 80 "|chrome_path| is provided, otherwise the tests could not be run") | 74 |
| 81 # Password internals page. | |
| 82 self.internals_page = "chrome://password-manager-internals/" | |
| 83 # The Website window. | |
| 84 self.website_window = None | |
| 85 # The WebsiteTests list. | |
| 86 self.websitetests = [] | 75 self.websitetests = [] |
| 76 |
| 87 # Map messages to the number of their appearance in the log. | 77 # Map messages to the number of their appearance in the log. |
| 88 self.message_count = { MESSAGE_ASK: 0, MESSAGE_SAVE: 0 } | 78 self.message_count = { MESSAGE_ASK: 0, MESSAGE_SAVE: 0 } |
| 89 # The tests needs two tabs to work. A new tab is opened with the first | 79 |
| 90 # GoTo. This is why we store here whether or not it's the first time to | 80 # A list of (test_name, test_type, test_success, failure_log). |
| 91 # execute GoTo. | |
| 92 self.first_go_to = True | |
| 93 # List of all tests results. | |
| 94 self.tests_results = [] | 81 self.tests_results = [] |
| 95 | 82 |
| 96 def AddWebsiteTest(self, websitetest): | 83 def AddWebsiteTest(self, websitetest): |
| 97 """Adds a WebsiteTest to the testing Environment. | 84 """Adds a WebsiteTest to the testing Environment. |
| 98 | 85 |
| 99 TODO(vabr): Currently, this is only called at most once for each | 86 TODO(vabr): Currently, this is only called at most once for each |
| 100 Environment instance. That is because to run all tests efficiently in | 87 Environment instance. That is because to run all tests efficiently in |
| 101 parallel, each test gets its own process spawned (outside of Python). | 88 parallel, each test gets its own process spawned (outside of Python). |
| 102 That makes sense, but then we should flatten the hierarchy of calls | 89 That makes sense, but then we should flatten the hierarchy of calls |
| 103 and consider making the 1:1 relation of environment to tests more | 90 and consider making the 1:1 relation of environment to tests more |
| 104 explicit. | 91 explicit. |
| 105 | 92 |
| 106 Args: | 93 Args: |
| 107 websitetest: The WebsiteTest instance to be added. | 94 websitetest: The WebsiteTest instance to be added. |
| 108 """ | 95 """ |
| 109 websitetest.environment = self | 96 websitetest.environment = self |
| 110 # TODO(vabr): Make driver a property of WebsiteTest. | 97 # TODO(vabr): Make driver a property of WebsiteTest. |
| 111 websitetest.driver = self.driver | 98 websitetest.driver = self.driver |
| 112 if not websitetest.username: | 99 if not websitetest.username: |
| 113 username_tag = ( | 100 username_tag = (self.passwords_tree.find( |
| 114 self.passwords_tree.find( | 101 ".//*[@name='%s']/username" % websitetest.name)) |
| 115 ".//*[@name='%s']/username" % websitetest.name)) | |
| 116 websitetest.username = username_tag.text | 102 websitetest.username = username_tag.text |
| 117 if not websitetest.password: | 103 if not websitetest.password: |
| 118 password_tag = ( | 104 password_tag = (self.passwords_tree.find( |
| 119 self.passwords_tree.find( | 105 ".//*[@name='%s']/password" % websitetest.name)) |
| 120 ".//*[@name='%s']/password" % websitetest.name)) | |
| 121 websitetest.password = password_tag.text | 106 websitetest.password = password_tag.text |
| 122 self.websitetests.append(websitetest) | 107 self.websitetests.append(websitetest) |
| 123 | 108 |
| 124 def ClearCache(self, clear_passwords): | 109 def _ClearBrowserDataInit(self): |
| 125 """Clear the browser cookies. If |clear_passwords| is true, clear all the | 110 """Opens and resets the chrome://settings/clearBrowserData dialog. |
| 126 saved passwords too. | 111 |
| 112 It unchecks all checkboxes, and sets the time range to the "beginning of |
| 113 time". |
| 114 """ |
| 115 |
| 116 self.driver.get("chrome://settings/clearBrowserData") |
| 117 self.driver.switch_to_frame("settings") |
| 118 |
| 119 time_range_selector = "#clear-browser-data-time-period" |
| 120 # TODO(vabr): Wait until time_range_selector is displayed instead. |
| 121 time.sleep(2) |
| 122 set_time_range = ( |
| 123 "var range = document.querySelector('{0}');".format( |
| 124 time_range_selector) + |
| 125 "range.value = 4" # 4 == the beginning of time |
| 126 ) |
| 127 self.driver.execute_script(set_time_range) |
| 128 |
| 129 all_cboxes_selector = ( |
| 130 "#clear-data-checkboxes [type=\"checkbox\"]") |
| 131 uncheck_all = ( |
| 132 "var checkboxes = document.querySelectorAll('{0}');".format( |
| 133 all_cboxes_selector ) + |
| 134 "for (var i = 0; i < checkboxes.length; ++i) {" |
| 135 " checkboxes[i].checked = false;" |
| 136 "}" |
| 137 ) |
| 138 self.driver.execute_script(uncheck_all) |
| 139 |
| 140 def _ClearDataForCheckbox(self, selector): |
| 141 """Causes the data associated with |selector| to be cleared. |
| 142 |
| 143 Opens chrome://settings/clearBrowserData, unchecks all checkboxes, then |
| 144 checks the one described by |selector|, then clears the corresponding |
| 145 browsing data for the full time range. |
| 127 | 146 |
| 128 Args: | 147 Args: |
| 129 clear_passwords : Clear all the passwords if the bool value is true. | 148 selector: describes the checkbox through which to delete the data. |
| 130 """ | 149 """ |
| 131 self.driver.get("chrome://settings/clearBrowserData") | 150 |
| 132 self.driver.switch_to_frame("settings") | 151 self._ClearBrowserDataInit() |
| 133 script = ( | 152 check_cookies_and_submit = ( |
| 134 "if (!document.querySelector('#delete-cookies-checkbox').checked)" | 153 "document.querySelector('{0}').checked = true;".format(selector) + |
| 135 " document.querySelector('#delete-cookies-checkbox').click();" | 154 "document.querySelector('#clear-browser-data-commit').click();" |
| 136 ) | 155 ) |
| 137 negation = "" | 156 self.driver.execute_script(check_cookies_and_submit) |
| 138 if clear_passwords: | 157 |
| 139 negation = "!" | 158 def _EnablePasswordSaving(self): |
| 140 script += ( | 159 """Make sure that password manager is enabled.""" |
| 141 "if (%sdocument.querySelector('#delete-passwords-checkbox').checked)" | 160 |
| 142 " document.querySelector('#delete-passwords-checkbox').click();" | |
| 143 % negation) | |
| 144 script += "document.querySelector('#clear-browser-data-commit').click();" | |
| 145 self.driver.execute_script(script) | |
| 146 time.sleep(2) | |
| 147 # Every time we do something to the cache let's enable password saving. | |
| 148 # TODO(melandory): We should check why it's off in a first place. | 161 # TODO(melandory): We should check why it's off in a first place. |
| 149 # TODO(melandory): Investigate, maybe there is no need to enable it that | 162 # TODO(melandory): Investigate, maybe there is no need to enable it that |
| 150 # often. | 163 # often. |
| 151 self.EnablePasswordsSaving() | |
| 152 | |
| 153 def EnablePasswordsSaving(self): | |
| 154 self.driver.get("chrome://settings") | 164 self.driver.get("chrome://settings") |
| 155 self.driver.switch_to_frame("settings") | 165 self.driver.switch_to_frame("settings") |
| 156 script = "document.getElementById('advanced-settings-expander').click();" | 166 script = "document.getElementById('advanced-settings-expander').click();" |
| 157 self.driver.execute_script(script) | 167 self.driver.execute_script(script) |
| 168 # TODO(vabr): Wait until element is displayed instead. |
| 158 time.sleep(2) | 169 time.sleep(2) |
| 159 script = ( | 170 script = ( |
| 160 "if (!document.querySelector('#password-manager-enabled').checked)" | 171 "document.querySelector('#password-manager-enabled').checked = true;") |
| 161 "{ document.querySelector('#password-manager-enabled').click();}") | |
| 162 self.driver.execute_script(script) | 172 self.driver.execute_script(script) |
| 163 time.sleep(2) | 173 time.sleep(2) |
| 164 | 174 |
| 165 def OpenTabAndGoToInternals(self, url): | 175 def _OpenNewTab(self): |
| 166 """If there is no |self.website_window|, opens a new tab and navigates to | 176 """Open a new tab, and loads the internals page in the old tab. |
| 167 |url| in the new tab. Navigates to the passwords internals page in the | |
| 168 first tab. Raises an exception otherwise. | |
| 169 | 177 |
| 170 Args: | 178 Returns: |
| 171 url: Url to go to in the new tab. | 179 A handle to the new tab. |
| 180 """ |
| 172 | 181 |
| 173 Raises: | 182 number_old_tabs = len(self.driver.window_handles) |
| 174 Exception: An exception is raised if |self.website_window| already | |
| 175 exists. | |
| 176 """ | |
| 177 if self.website_window: | |
| 178 raise Exception("Error: The window was already opened.") | |
| 179 | |
| 180 self.driver.get("chrome://newtab") | |
| 181 # There is no straightforward way to open a new tab with chromedriver. | 183 # There is no straightforward way to open a new tab with chromedriver. |
| 182 # One work-around is to go to a website, insert a link that is going | 184 # One work-around is to go to a website, insert a link that is going |
| 183 # to be opened in a new tab, click on it. | 185 # to be opened in a new tab, and click on it. |
| 186 self.driver.get("about:blank") |
| 184 a = self.driver.execute_script( | 187 a = self.driver.execute_script( |
| 185 "var a = document.createElement('a');" | 188 "var a = document.createElement('a');" |
| 186 "a.target = '_blank';" | 189 "a.target = '_blank';" |
| 187 "a.href = arguments[0];" | 190 "a.href = 'about:blank';" |
| 188 "a.innerHTML = '.';" | 191 "a.innerHTML = '.';" |
| 189 "document.body.appendChild(a);" | 192 "document.body.appendChild(a);" |
| 190 "return a;", | 193 "return a;") |
| 191 url) | 194 a.click() |
| 195 while number_old_tabs == len(self.driver.window_handles): |
| 196 time.sleep(1) # Wait until the new tab is opened. |
| 192 | 197 |
| 193 a.click() | 198 new_tab = self.driver.window_handles[-1] |
| 194 time.sleep(1) | 199 self.driver.get(INTERNALS_PAGE_URL) |
| 200 self.driver.switch_to_window(new_tab) |
| 201 return new_tab |
| 195 | 202 |
| 196 self.website_window = self.driver.window_handles[-1] | 203 def _DidStringAppearUntilTimeout(self, strings, timeout): |
| 197 self.driver.get(self.internals_page) | 204 """Checks whether some of |strings| appeared in the current page. |
| 198 self.driver.switch_to_window(self.website_window) | |
| 199 | 205 |
| 200 def SwitchToInternals(self): | 206 Waits for up to |timeout| seconds until at least one of |strings| is |
| 201 """Switches from the Website window to internals tab.""" | 207 shown in the current page. Updates self.message_count with the current |
| 202 self.driver.switch_to_window(self.internals_window) | 208 number of occurrences of the shown string. Assumes that at most |
| 203 | 209 one of |strings| is newly shown. |
| 204 def SwitchFromInternals(self): | |
| 205 """Switches from internals tab to the Website window.""" | |
| 206 self.driver.switch_to_window(self.website_window) | |
| 207 | |
| 208 def _DidMessageAppearUntilTimeout(self, log_message, timeout): | |
| 209 """Checks whether the save password prompt is shown. | |
| 210 | 210 |
| 211 Args: | 211 Args: |
| 212 log_message: Log message to look for in the password internals. | 212 strings: A list of strings to look for. |
| 213 timeout: There is some delay between the login and the password | 213 timeout: If any such string does not appear within the first |timeout| |
| 214 internals update. The method checks periodically during the first | 214 seconds, it is considered a no-show. |
| 215 |timeout| seconds if the internals page reports the prompt being | |
| 216 shown. If the prompt is not reported shown within the first | |
| 217 |timeout| seconds, it is considered not shown at all. | |
| 218 | 215 |
| 219 Returns: | 216 Returns: |
| 220 True if the save password prompt is shown. | 217 True if one of |strings| is observed until |timeout|, False otherwise. |
| 221 False otherwise. | |
| 222 """ | 218 """ |
| 219 |
| 223 log = self.driver.find_element_by_css_selector("#log-entries") | 220 log = self.driver.find_element_by_css_selector("#log-entries") |
| 224 count = log.text.count(log_message) | 221 while timeout: |
| 222 for string in strings: |
| 223 count = log.text.count(string) |
| 224 if count > self.message_count[string]: |
| 225 self.message_count[string] = count |
| 226 return True |
| 227 time.sleep(1) |
| 228 timeout -= 1 |
| 229 return False |
| 225 | 230 |
| 226 if count > self.message_count[log_message]: | 231 def CheckForNewString(self, strings, string_should_show_up, error): |
| 227 self.message_count[log_message] = count | 232 """Checks that |strings| show up on the internals page as it should. |
| 228 return True | |
| 229 elif timeout > 0: | |
| 230 time.sleep(1) | |
| 231 return self._DidMessageAppearUntilTimeout(log_message, timeout - 1) | |
| 232 else: | |
| 233 return False | |
| 234 | 233 |
| 235 def CheckForNewMessage(self, log_message, message_should_show_up, | 234 Switches to the internals page and looks for a new instances of |strings| |
| 236 error_message, timeout=15): | 235 being shown up there. It checks that |string_should_show_up| is true if |
| 237 """Detects whether the save password prompt is shown. | 236 and only if at leas one string from |strings| shows up, and throws an |
| 237 Exception if that check fails. |
| 238 | 238 |
| 239 Args: | 239 Args: |
| 240 log_message: Log message to look for in the password internals. The | 240 strings: A list of strings to look for in the internals page. |
| 241 only valid values are the constants MESSAGE_* defined at the | 241 string_should_show_up: Whether or not at least one string from |strings| |
| 242 beginning of this file. | 242 is expected to be shown. |
| 243 message_should_show_up: Whether or not the message is expected to be | 243 error: Error message for the exception. |
| 244 shown. | |
| 245 error_message: Error message for the exception. | |
| 246 timeout: There is some delay between the login and the password | |
| 247 internals update. The method checks periodically during the first | |
| 248 |timeout| seconds if the internals page reports the prompt being | |
| 249 shown. If the prompt is not reported shown within the first | |
| 250 |timeout| seconds, it is considered not shown at all. | |
| 251 | 244 |
| 252 Raises: | 245 Raises: |
| 253 Exception: An exception is raised in case the result does not match the | 246 Exception: (See above.) |
| 254 expectation | |
| 255 """ | 247 """ |
| 256 if (self._DidMessageAppearUntilTimeout(log_message, timeout) != | |
| 257 message_should_show_up): | |
| 258 raise Exception(error_message) | |
| 259 | 248 |
| 260 def AllTests(self, prompt_test): | 249 self.driver.switch_to_window(self.internals_window) |
| 261 """Runs the tests on all the WebsiteTests. | 250 try: |
| 251 if (self._DidStringAppearUntilTimeout(strings, 15) != |
| 252 string_should_show_up): |
| 253 raise Exception(error) |
| 254 finally: |
| 255 self.driver.switch_to_window(self.website_window) |
| 262 | 256 |
| 263 TODO(vabr): Currently, "all tests" always means one. | 257 def DeleteCookies(self): |
| 258 """Deletes cookies via the settings page.""" |
| 259 |
| 260 self._ClearDataForCheckbox("#delete-cookies-checkbox") |
| 261 |
| 262 def RunTestsOnSites(self, test_type): |
| 263 """Runs the specified test on the known websites. |
| 264 |
| 265 Also saves the test results in the environment. Note that test types |
| 266 differ in their requirements on whether the save password prompt |
| 267 should be displayed. Make sure that such requirements are consistent |
| 268 with the enable_automatic_password_saving argument passed to |self| |
| 269 on construction. |
| 264 | 270 |
| 265 Args: | 271 Args: |
| 266 prompt_test: If True, tests caring about showing the save-password | 272 test_type: A test identifier understood by WebsiteTest.run_test(). |
| 267 prompt are going to be run, otherwise tests which don't care about | 273 """ |
| 268 the prompt are going to be run. | |
| 269 | 274 |
| 270 Raises: | 275 self.DeleteCookies() |
| 271 Exception: An exception is raised if the tests fail. | 276 self._ClearDataForCheckbox("#delete-passwords-checkbox") |
| 272 """ | 277 self._EnablePasswordSaving() |
| 273 if prompt_test: | |
| 274 self.PromptTestList(self.websitetests) | |
| 275 else: | |
| 276 self.TestList(self.websitetests) | |
| 277 | 278 |
| 278 def Test(self, tests, prompt_test): | |
| 279 """Runs the tests on websites named in |tests|. | |
| 280 | |
| 281 Args: | |
| 282 tests: A list of the names of the WebsiteTests that are going to be | |
| 283 tested. | |
| 284 prompt_test: If True, tests caring about showing the save-password | |
| 285 prompt are going to be run, otherwise tests which don't care about | |
| 286 the prompt are going to be executed. | |
| 287 | |
| 288 Raises: | |
| 289 Exception: An exception is raised if the tests fail. | |
| 290 """ | |
| 291 websitetests = [] | |
| 292 for websitetest in self.websitetests: | 279 for websitetest in self.websitetests: |
| 293 if websitetest.name in tests: | |
| 294 websitetests.append(websitetest) | |
| 295 | |
| 296 if prompt_test: | |
| 297 self.PromptTestList(websitetests) | |
| 298 else: | |
| 299 self.TestList(websitetests) | |
| 300 | |
| 301 def TestList(self, websitetests): | |
| 302 """Runs the tests on the websites in |websitetests|. | |
| 303 | |
| 304 Args: | |
| 305 websitetests: A list of WebsiteTests that are going to be tested. | |
| 306 | |
| 307 Raises: | |
| 308 Exception: An exception is raised if the tests fail. | |
| 309 """ | |
| 310 self.ClearCache(True) | |
| 311 | |
| 312 for websitetest in websitetests: | |
| 313 successful = True | 280 successful = True |
| 314 error = "" | 281 error = "" |
| 315 try: | 282 try: |
| 316 websitetest.was_run = True | 283 websitetest.RunTest(test_type) |
| 317 websitetest.WrongLoginTest() | |
| 318 websitetest.SuccessfulLoginTest() | |
| 319 self.ClearCache(False) | |
| 320 websitetest.SuccessfulLoginWithAutofilledPasswordTest() | |
| 321 self.ClearCache(True) | |
| 322 websitetest.SuccessfulLoginTest() | |
| 323 self.ClearCache(True) | |
| 324 except Exception as e: | 284 except Exception as e: |
| 325 successful = False | 285 successful = False |
| 326 error = e.message | 286 error = e.message |
| 327 self.tests_results.append(TestResult(websitetest.name, "normal", | 287 self.tests_results.append( |
| 328 successful, error)) | 288 (websitetest.name, test_type, successful, error)) |
| 329 | |
| 330 | |
| 331 def PromptTestList(self, websitetests): | |
| 332 """Runs the prompt tests on the websites in |websitetests|. | |
| 333 | |
| 334 Args: | |
| 335 websitetests: A list of WebsiteTests that are going to be tested. | |
| 336 | |
| 337 Raises: | |
| 338 Exception: An exception is raised if the tests fail. | |
| 339 """ | |
| 340 self.ClearCache(True) | |
| 341 | |
| 342 for websitetest in websitetests: | |
| 343 successful = True | |
| 344 error = "" | |
| 345 try: | |
| 346 websitetest.was_run = True | |
| 347 websitetest.PromptTest() | |
| 348 except Exception as e: | |
| 349 successful = False | |
| 350 error = e.message | |
| 351 self.tests_results.append(TestResult(websitetest.name, "prompt", | |
| 352 successful, error)) | |
| 353 | 289 |
| 354 def Quit(self): | 290 def Quit(self): |
| 355 """Closes the tests.""" | 291 """Shuts down the driver.""" |
| 356 # Close the webdriver. | 292 |
| 357 self.driver.quit() | 293 self.driver.quit() |
| OLD | NEW |