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

Unified 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: log 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 side-by-side diff with in-line comments
Download patch
Index: components/test/data/password_manager/environment.py
diff --git a/components/test/data/password_manager/environment.py b/components/test/data/password_manager/environment.py
new file mode 100644
index 0000000000000000000000000000000000000000..2a17225a160a7b2e1c0291d05264cc2e0885c8a5
--- /dev/null
+++ b/components/test/data/password_manager/environment.py
@@ -0,0 +1,242 @@
+"""The testing Environment class."""
+
+import shutil
+import time
+
+from selenium import webdriver
+from selenium.webdriver.chrome.options import Options
+from xml.etree import ElementTree
+
+
+class Environment:
+ """Sets up the testing Environment. """
+
+ def __init__(self, chrome_path, chromedriver_path,
+ profile_path, passwords_path,
+ log_to_screen, log_file):
+ """Creates a new testing Environment.
+
+ Args:
+ chrome_path: The chrome binary file.
+ chromedriver_path: The chromedriver binary file.
+ profile_path: The testing profile folder.
+ passwords_path: The usernames and passwords file.
+ log_to_screen: If set, the tests log is going to be shown on the screen.
+ log_file: The file where to store the log.
+ """
+ # Cleaning the profile folder.
+ try:
+ shutil.rmtree(profile_path)
+ except Exception, e:
+ self.Log(e)
vabr (Chromium) 2014/05/16 09:36:00 This deservers a comment on why is it OK to procee
rchtara 2014/05/20 08:24:47 Done.
+ options = Options()
+ options.add_argument("enable-automatic-password-saving")
+ options.add_argument("enable-password-manager-internals-ui")
vabr (Chromium) 2014/05/16 09:36:00 nit: Since yesterday, this is no more needed. :)
rchtara 2014/05/22 08:44:38 Yes, i have an old version of code, so i need it.
+ # Chrome path.
+ options.binary_location = chrome_path
+ # Testing profile path.
+ options.add_argument("user-data-dir=%s" % profile_path)
+
+ # The webdriver. It's possible to choose the port the service is going to
+ # run on. If it's left to 0, a free port will be found.
+ self.driver = webdriver.Chrome(chromedriver_path, 0, options)
+ # The password internals window.
+ self.internals_window = self.driver.current_window_handle
+ # Password internals page.
+ self.internals_page = "chrome://password-manager-internals/"
+ # The Website window.
+ self.websitewindow = None
+ # The Websites list.
+ self.websites = []
+ # An xml tree filled with logins and passwords.
+ self.passwords_tree = None
+ if passwords_path:
+ self.passwords_tree = ElementTree.parse(passwords_path).getroot()
+ # The Websites list for which we expect the test to be working.
+ self.working_tests = []
+ # The number of the save operations done through all the tests.
vabr (Chromium) 2014/05/16 09:36:00 nit: "through all" contains 2 spaces instead of 1
rchtara 2014/05/20 08:24:47 Done.
+ self.save_count = 0
+
+ self.log_to_screen = log_to_screen
+ self.log_file = None
+ if log_file:
+ self.log_file = open(log_file,'w')
+
+ def AddWebsite(self,
+ website,
+ disabled=False):
+ """Adds a Website to the testing Environment.
vabr (Chromium) 2014/05/16 09:36:00 Actually, what do you think of renaming Website to
rchtara 2014/05/20 08:24:47 Done.
+
+ Args:
+ website: The Website instance that's going to be added to the testing
+ Environment.
+ disabled: Test is disabled.
+ """
+ website.environment = self
+ website.driver = self.driver
+ if self.passwords_tree is not None:
vabr (Chromium) 2014/05/16 09:36:00 nit: Just use if self.passwords_tree:
rchtara 2014/05/20 08:24:47 I got this warning when I tied to replace this Non
vabr (Chromium) 2014/05/20 14:47:25 Fair enough. Your test for "is not None" is actual
rchtara 2014/05/22 08:44:38 No problem
+ if not website.username:
+ username_tag = (
+ self.passwords_tree.find(
+ ".//*[@name='%s']/username" % website.name))
+ if username_tag.text:
+ website.username = username_tag.text
+ if not website.password:
+ password_tag = (
+ self.passwords_tree.find(
+ ".//*[@name='%s']/password" % website.name))
+ if password_tag.text:
+ website.password = password_tag.text
+ self.websites.append(website)
+ if disabled == False:
vabr (Chromium) 2014/05/16 09:36:00 nit: Just use: if not disabled:
rchtara 2014/05/20 08:24:47 Done.
+ self.working_tests.append(website.name)
+
+ def RemoveAllPasswords(self, websites):
+ """Removes the stored passwords for all Websites.
vabr (Chromium) 2014/05/16 09:36:00 Why don't you just flush all the stored passwords,
rchtara 2014/05/20 08:24:47 Done.
+
+ Args:
+ websites: The Websites which the passwords are going to be removed.
+ """
+ self.Log("\nRemoveAllPasswords\n")
+ self.driver.get("chrome://settings/passwords")
+ self.driver.switch_to_frame("settings")
+ for website in websites:
+ urls = self.GetURLs()
+ website.RemoveAllPasswords(urls)
+
+ def GetURLs(self):
+ """Gets all URLs of the saved passwords in the chrome://settings/passwords.
+
+ Returns:
+ A list of the URLs.
+ """
+ deletable_passwords = self.driver.find_elements_by_css_selector(
+ "#saved-passwords-list .deletable-item")
+ urls = []
+ for entry in deletable_passwords:
+ urls.append(entry.find_element_by_class_name("url").text)
+ return urls
+
+ def OpenTabAndGoInternal(self):
vabr (Chromium) 2014/05/16 09:36:00 nit: Please rename to OpenTabAndGoToInternals ("go
rchtara 2014/05/20 08:24:47 Done.
+ """Opens a new tab and navigates to passwords internals page in the first
vabr (Chromium) 2014/05/16 09:36:00 The comment does not seem to match the code exactl
rchtara 2014/05/20 08:24:47 Done.
+ tab."""
+ if not self.websitewindow:
+ self.driver.get("https://google.com")
vabr (Chromium) 2014/05/16 09:36:00 Would chrome://newtab work instead of google.com?
rchtara 2014/05/20 08:24:47 I updated the test to go to the url of the first w
vabr (Chromium) 2014/05/20 14:47:25 Great, thanks for fixing this!
rchtara 2014/05/22 08:44:38 Thanks :)
+ # There is no straightforward way to open a new tab with chromedriver.
+ # One work-around is to go to a website, insert a link that is going
+ # to be opened in a new tab, click on it. To avoid that the chrome popup
+ # blocker blocks the new tab, we need to choose a trusted website which
+ # is google.com.
+ a = self.driver.execute_script(
+ "var a = document.createElement('a');"
+ "a.target = '_blank';"
+ "a.href = arguments[0];"
+ "a.innerHTML = '.';"
+ "document.body.appendChild(a);"
+ "return a;",
+ "https://google.com")
+
+ a.click()
+ time.sleep(1)
vabr (Chromium) 2014/05/16 09:36:00 It's a bit unfortunate that this sleep() does not
rchtara 2014/05/20 08:24:47 I don't think it's make sense to do that.max_durat
vabr (Chromium) 2014/05/20 14:47:25 OK, makes sense, I misunderstood the function of m
rchtara 2014/05/22 08:44:38 Done.
+
+ self.websitewindow = self.driver.window_handles[-1]
+ self.driver.get(self.internals_page)
+ self.driver.switch_to_window(self.websitewindow)
+
+ def SwitchToInternals(self):
+ """Switches from the Website window to internals tab."""
+ self.driver.switch_to_window(self.internals_window)
+
+ def SwitchFromInternals(self):
+ """Switches from internals tab to the Website window."""
+ self.driver.switch_to_window(self.websitewindow)
+
+ def CheckPromptIsNotShown(self, expected, msg, timeout=10):
+ """Checks if the prompt was shown: If the prompt is shown when it shouldn't
vabr (Chromium) 2014/05/16 09:36:00 nit: CheckPromptIsNotShown ... Checks if the promp
rchtara 2014/05/20 08:24:47 Done.
+ be or is not shown when it should be, raise an exception.
+
+ Args:
+ expected: Whether or not the prompt is expected to be shown.
+ msg: Error message for the exception.
+ timeout: There is some delay between the login and the password
+ internals update. In case nothing is detected, the method is going to
+ wait and execute itself recursively until the time will end.
vabr (Chromium) 2014/05/16 09:36:00 This is not clear (and also does not mention the t
rchtara 2014/05/20 08:24:47 Done.
+
+ Raises:
+ Exception: An exception is raised in case there a problem.
+ """
+ if expected:
+ self.save_count += 1
+ log = self.driver.find_element_by_css_selector("#log-entries")
+ count = log.text.count("Message: Decision: SAVE the password")
vabr (Chromium) 2014/05/16 09:36:00 This is not correct. The message actually says tha
rchtara 2014/05/20 08:24:47 Done.
+
+ if count < self.save_count and timeout > 0:
+ time.sleep(1)
+ self.CheckPromptIsNotShown(False, msg, timeout - 1)
+
+ elif not self.save_count == count:
+ raise Exception(msg)
+
+ def Log(self, text):
vabr (Chromium) 2014/05/16 09:36:00 Please use the standard Python logging support ins
rchtara 2014/05/20 08:24:47 Done.
+ """Writes to the log.
+ Args:
+ text: Text to be written.
+ """
+ if self.log_to_screen:
+ print text
+ if self.log_file:
+ self.log_file.write("%s \n" % text)
+
+ def TestList(self, websites):
+ """Runs the tests on many Websites.
vabr (Chromium) 2014/05/16 09:36:00 nit: "many Websites" is unnecessarily vague. Just
rchtara 2014/05/20 08:24:47 Done.
vabr (Chromium) 2014/05/20 14:47:25 That's not what I meant: you still kept "many". I
rchtara 2014/05/22 08:44:38 sorry :)
+ Args:
+ websites: A list of Websites that are going to be tested.
+ Raises:
+ Exception: An exception is raised if the tests fail.
+ """
+ self.RemoveAllPasswords(websites)
+
+ self.OpenTabAndGoInternal()
+ for website in websites:
+ website.WrongLoginTest()
+ website.SuccessfulLoginTest()
+ website.SuccessfulLoginWithAutofilledPasswordTest()
+
+ self.RemoveAllPasswords(websites)
+ for website in websites:
+ website.SuccessfulLoginAfterDeletionTest()
+
+ def AllTests(self):
+ """Runs the tests on all the websites.
+ Raises:
+ Exception: An exception is raised if the tests fail.
+ """
+ self.TestList(self.websites)
+
+ def WorkingTests(self):
+ """Runs the tests on all the working websites.
+ Raises:
+ Exception: An exception is raised if the tests fail.
+ """
+ self.Test(self.working_tests)
+
+ def Test(self, tests):
+ """Runs the tests on many websites.
+ Args:
+ tests: A list of the names of the websites that are going to be tested.
+ Raises:
+ Exception: An exception is raised if the tests fail.
+ """
+ websites = []
+ for website in self.websites:
+ if website.name in tests:
+ websites.append(website)
+ self.TestList(websites)
+
+ def Quit(self):
+ """Closes the tests."""
+ # Close the log file if it's open.
+ if self.log_file:
+ self.log_file.close()
+ # Close the webdriver.
+ self.driver.quit()

Powered by Google App Engine
This is Rietveld 408576698