Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: components/test/data/password_manager/environment.py

Issue 273523004: Password Manager testing automation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: renaming Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 """The testing Environment class."""
2
3 import logging
4 import shutil
5 import time
6
7 from selenium import webdriver
8 from selenium.common.exceptions import NoSuchElementException
9 from selenium.common.exceptions import WebDriverException
10 from selenium.webdriver.chrome.options import Options
11 from xml.etree import ElementTree
12
13
14 class Environment:
15 """Sets up the testing Environment. """
16
17 def __init__(self, chrome_path, chromedriver_path, profile_path,
18 passwords_path, enable_automatic_password_saving,
19 numeric_level, log_screen, log_file):
vabr (Chromium) 2014/05/20 14:47:25 nit: log_screen -> log_to_console
vabr (Chromium) 2014/05/20 14:47:25 Please provide default values for numeric_level, l
rchtara 2014/05/22 08:44:38 Done.
rchtara 2014/05/22 08:44:38 Done.
20 """Creates a new testing Environment.
21
22 Args:
23 chrome_path: The chrome binary file.y
vabr (Chromium) 2014/05/20 14:47:25 typo: "y" at the end of the line
rchtara 2014/05/22 08:44:38 Done.
24 chromedriver_path: The chromedriver binary file.
25 profile_path: The testing profile folder.
vabr (Chromium) 2014/05/20 14:47:25 nit: "profile" -> "Chrome profile", just for clari
rchtara 2014/05/22 08:44:38 Done.
26 passwords_path: The usernames and passwords file.
27 enable_automatic_password_saving: If set, the passwords are going to be
28 saved without showing the prompt.
29 numeric_level: The log numeric level.
vabr (Chromium) 2014/05/20 14:47:25 nit: "log" -> "log verbosity"
rchtara 2014/05/22 08:44:38 Done.
30 log_screen: If set, the tests log is going to be shown on the screen.
vabr (Chromium) 2014/05/20 14:47:25 nit: change "screen" to console also in the commen
vabr (Chromium) 2014/05/20 14:47:25 nit: "tests log is going to be" -> "debug logs wil
vabr (Chromium) 2014/05/20 14:47:25 nit: "set" -> "true"
rchtara 2014/05/22 08:44:38 Done.
rchtara 2014/05/22 08:44:38 Done.
rchtara 2014/05/22 08:44:38 Done.
31 log_file: The file where to store the log.
vabr (Chromium) 2014/05/20 14:47:25 nit: Comment on what happens if it is empty.
rchtara 2014/05/22 08:44:38 Done.
32
33 Raises:
34 Exception: An exception is raised if |profile_path| folder could not be
35 removed.
36 """
37 # Setting up the login.
38 if numeric_level is not None:
39 if log_file:
40 # Set up logging to file.
41 logging.basicConfig(level=numeric_level,
42 filename=log_file,
43 filemode='w')
44
45 if log_screen:
46 console = logging.StreamHandler()
47 console.setLevel(numeric_level)
48 # Add the handler to the root logger.
49 logging.getLogger('').addHandler(console)
50
51 elif log_screen:
52 logging.basicConfig(level=numeric_level)
53
54 # Cleaning the profile folder.
55 try:
56 shutil.rmtree(profile_path)
57 except Exception, e:
58 # The tests execution can continue, but this make them less stable.
59 logging.error("""Error: %s.\n The tests execution is continuing. But
vabr (Chromium) 2014/05/20 14:47:25 I don't think you use """ correctly here. If you o
rchtara 2014/05/22 08:44:38 Done.
60 the tests are going to be less stable.""" % e)
vabr (Chromium) 2014/05/20 14:47:25 Please be more specific: write what is the error,
rchtara 2014/05/22 08:44:38 Done.
61 options = Options()
62 if enable_automatic_password_saving:
63 options.add_argument("enable-automatic-password-saving")
64 options.add_argument("enable-password-manager-internals-ui")
vabr (Chromium) 2014/05/20 14:47:25 You probably missed my comment earlier: enable-pas
rchtara 2014/05/22 08:44:38 I didn't update my chromium yet, so I will keep us
65 # Chrome path.
66 options.binary_location = chrome_path
67 # Testing profile path.
68 options.add_argument("user-data-dir=%s" % profile_path)
69
70 # 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.
72 self.driver = webdriver.Chrome(chromedriver_path, 0, options)
73 # The password internals window.
74 self.internals_window = self.driver.current_window_handle
75 # Password internals page.
76 self.internals_page = "chrome://password-manager-internals/"
77 # The Website window.
78 self.website_window = None
79 # The WebsiteTests list.
80 self.websitetests = []
81 # An xml tree filled with logins and passwords.
82 self.passwords_tree = None
83 if passwords_path:
84 self.passwords_tree = ElementTree.parse(passwords_path).getroot()
85 # The enabled WebsiteTests list.
86 self.working_tests = []
87 # The number of the save operations done through all the tests.
88 self.save_count = 0
vabr (Chromium) 2014/05/20 14:47:25 Note: I see you use this to deal with the internal
rchtara 2014/05/22 08:44:38 No, it's going make it harder, because I will need
89 # Show whether or not it's the first time to execute GoTo.
vabr (Chromium) 2014/05/20 14:47:25 "Show"? It's not clear how and to whom this is sho
rchtara 2014/05/22 08:44:38 Done.
90 self.first_go_to = True
91
92 def AddWebsiteTest(self, websitetest, disabled=False):
93 """Adds a WebsiteTest to the testing Environment.
94
95 Args:
96 websitetest: The WebsiteTest instance that's going to be added to the
vabr (Chromium) 2014/05/20 14:47:25 nit: You can simply write: "The WebsiteTest instan
rchtara 2014/05/22 08:44:38 Done.
97 testing Environment.
98 disabled: Test is disabled.
vabr (Chromium) 2014/05/20 14:47:25 nit: Whether test is disabled.
rchtara 2014/05/22 08:44:38 Done.
99 """
100 websitetest.environment = self
101 websitetest.driver = self.driver
102 if self.passwords_tree is not None:
103 if not websitetest.username:
104 username_tag = (
105 self.passwords_tree.find(
106 ".//*[@name='%s']/username" % websitetest.name))
107 if username_tag.text:
108 websitetest.username = username_tag.text
109 if not websitetest.password:
110 password_tag = (
111 self.passwords_tree.find(
112 ".//*[@name='%s']/password" % websitetest.name))
113 if password_tag.text:
114 websitetest.password = password_tag.text
115 self.websitetests.append(websitetest)
116 if not disabled:
117 self.working_tests.append(websitetest.name)
118
119 def RemoveAllPasswords(self):
120 """Removes all the stored passwords."""
121 logging.info("\nRemoveAllPasswords\n")
122 self.driver.get("chrome://settings/passwords")
123 self.driver.switch_to_frame("settings")
124 while True:
125 try:
126 self.driver.execute_script("document.querySelector('"
127 "#saved-passwords-list .row-delete-button').click()")
128 time.sleep(1)
129 except NoSuchElementException:
130 break
131 except WebDriverException:
132 break
133
134 def OpenTabAndGoToInternals(self, url):
135 """If there is no |self.website_window|, opens a new tab and navigates to
136 |url| in the new tab. Navigates to the passwords internals page in the
137 first tab. Raises an exception otherwise.
vabr (Chromium) 2014/05/20 14:47:25 It's not clear what "otherwise" refers to. I belie
rchtara 2014/05/22 08:44:38 Done.
138
139 Args:
140 url: Url to go to in the new tab.
141
142 Raises:
143 Exception: An exception is raised if |self.website_window| already exists.
144 """
145 if not self.website_window:
vabr (Chromium) 2014/05/20 14:47:25 nit: Consider starting with if self.website_window
rchtara 2014/05/22 08:44:38 Done.
146 self.driver.get("chrome://newtab")
147 # There is no straightforward way to open a new tab with chromedriver.
148 # One work-around is to go to a website, insert a link that is going
149 # to be opened in a new tab, click on it.
150 a = self.driver.execute_script(
151 "var a = document.createElement('a');"
152 "a.target = '_blank';"
153 "a.href = arguments[0];"
154 "a.innerHTML = '.';"
155 "document.body.appendChild(a);"
156 "return a;",
157 url)
158
159 a.click()
160 time.sleep(1)
161
162 self.website_window = self.driver.window_handles[-1]
163 self.driver.get(self.internals_page)
164 self.driver.switch_to_window(self.website_window)
165 else:
166 raise Exception("Error: The window was already opened.")
167
168 def SwitchToInternals(self):
169 """Switches from the Website window to internals tab."""
170 self.driver.switch_to_window(self.internals_window)
171
172 def SwitchFromInternals(self):
173 """Switches from internals tab to the Website window."""
174 self.driver.switch_to_window(self.website_window)
175
176 def CheckPrompt(self, log_message, prompt_should_show_up,
177 error_message, timeout=10):
178 """Detects whether the save password prompt is shown, and raises an
179 exception if the result does not match the expectation.
180
181 Args:
182 log_message: Log message to look for in the password internals.
183 prompt_should_show_up: Whether or not the prompt is expected to be shown.
184 error_message: Error message for the exception .
vabr (Chromium) 2014/05/20 14:47:25 nit: Remove the two spaces at the end of the sente
rchtara 2014/05/22 08:44:38 Done.
185 timeout: There is some delay between the login and the password
186 internals update. The method checks periodically during the first
187 |timeout| seconds if the internals page reports the prompt being
188 shown. If the prompt is not reported shown within the first
189 |timeout| seconds, it is considered not shown at all.
190
191 Raises:
192 Exception: An exception is raised in case there is a problem.
vabr (Chromium) 2014/05/20 14:47:25 nit: "there is a problem" -> "the result does not
rchtara 2014/05/22 08:44:38 Done.
193 """
194 if prompt_should_show_up:
195 self.save_count += 1
196 log = self.driver.find_element_by_css_selector("#log-entries")
197 count = log.text.count(log_message)
198
199 if count < self.save_count and timeout > 0:
200 time.sleep(1)
201 self.CheckPrompt(log_message, False, error_message, timeout - 1)
vabr (Chromium) 2014/05/20 14:47:25 You hard-code False as the "prompt_should_show_up"
rchtara 2014/05/22 08:44:38 Done.
202
203 elif not self.save_count == count:
204 raise Exception(error_message)
205
206 def AllTests(self, prompt_test):
207 """Runs the tests on all the WebsiteTests.
vabr (Chromium) 2014/05/20 14:47:25 typo: two consequent spaces between "the" and "Web
rchtara 2014/05/22 08:44:38 Done.
208
209 Args:
210 prompt_test: Prompt tests or normal tests.
vabr (Chromium) 2014/05/20 14:47:25 Please explain what are "prompt tests". The most p
rchtara 2014/05/22 08:44:38 Done.
211
212 Raises:
213 Exception: An exception is raised if the tests fail.
214 """
215 if prompt_test:
216 self.PromptTestList(self.websitetests)
217 else:
218 self.TestList(self.websitetests)
219
220 def WorkingTests(self, prompt_test):
221 """Runs the tests on all the enabled WebsiteTests.
222
223 Args:
224 prompt_test: Prompt tests or normal tests.
225
226 Raises:
227 Exception: An exception is raised if the tests fail.
228 """
229 self.Test(self.working_tests, prompt_test)
230
231 def Test(self, tests, prompt_test):
232 """Runs the tests on many WebsiteTests.
vabr (Chromium) 2014/05/20 14:47:25 many WebsiteTests -> websites named in |tests| Al
rchtara 2014/05/22 08:44:38 Done.
233
234 Args:
235 tests: A list of the names of the WebsiteTests that are going to be
236 tested.
237 prompt_test: Prompt tests or normal tests.
238
239 Raises:
240 Exception: An exception is raised if the tests fail.
241 """
242 websitetests = []
243 for websitetest in self.websitetests:
244 if websitetest.name in tests:
245 websitetests.append(websitetest)
246
247 if prompt_test:
248 self.PromptTestList(websitetests)
249 else:
250 self.TestList(websitetests)
251
252 def TestList(self, websitetests):
253 """Runs the tests on many WebsiteTests.
254
255 Args:
256 websitetests: A list of WebsiteTests that are going to be tested.
257
258 Raises:
259 Exception: An exception is raised if the tests fail.
260 """
261 self.RemoveAllPasswords()
262
263 for websitetest in websitetests:
264 websitetest.WrongLoginTest()
265 websitetest.SuccessfulLoginTest()
266 websitetest.SuccessfulLoginWithAutofilledPasswordTest()
267
268 self.RemoveAllPasswords()
269 for websitetest in websitetests:
270 websitetest.SuccessfulLoginTest()
271
272 def PromptTestList(self, websitetests):
273 """Runs the prompt tests on many WebsiteTests.
274
275 Args:
276 websitetests: A list of WebsiteTests that are going to be tested.
277
278 Raises:
279 Exception: An exception is raised if the tests fail.
280 """
281 self.RemoveAllPasswords()
282
283 for websitetest in websitetests:
284 websitetest.PromptTest()
285
286 def Quit(self):
287 """Closes the tests."""
288 # Close the webdriver.
289 self.driver.quit()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698