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

Side by Side Diff: components/test/data/password_manager/automated_tests/run_tests.py

Issue 873333002: [Password manager tests] Write to spreadsheets. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 # Copyright 2014 The Chromium Authors. All rights reserved. 2 # Copyright 2014 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """This file allows the bots to be easily configure and run the tests.""" 6 """This file allows the bots to be easily configure and run the tests.
7 7
8 Running this script requires passing --config-path with a path to a config file
9 of the following structure:
10 [credentials]
11 pkey=full_path
12 client_email=email_assigned_by_google_dev_console
13 [drive]
14 key=sheet_key_from_sheet_url
15 [data_files]
16 passwords_path=full_path_to_the_file_with_passwords
17 """
18 from Sheet import Sheet
19 from apiclient.discovery import build
20 from datetime import datetime
21 from gdata.gauth import OAuth2TokenFromCredentials
22 from gdata.spreadsheet.service import SpreadsheetsService
23 from oauth2client.client import SignedJwtAssertionCredentials
24 import ConfigParser
8 import argparse 25 import argparse
26 import httplib2
27 import oauth2client.tools
9 import os 28 import os
10 import tempfile 29 import tempfile
11 30
12 from environment import Environment 31 from environment import Environment
13 import tests 32 import tests
14 33
34 _CREDENTIAL_SCOPES = "https://spreadsheets.google.com/feeds"
35
36 # TODO(melandory): Function _authenticate belongs to separate module.
37 def _authenticate(pkey, client_email):
38 """ Authenticates user.
39
40 Args:
41 pkey: Full path to file with private key generated by Google
42 Developer Console.
43 client_email: Email address corresponding to private key and also
44 generated by Google Developer Console.
45 """
46 http, token = None, None
47 with open(pkey) as pkey_file:
48 private_key = pkey_file.read()
49 credentials = SignedJwtAssertionCredentials(
50 client_email, private_key, _CREDENTIAL_SCOPES)
51 http = httplib2.Http()
52 http = credentials.authorize(http)
53 build('drive', 'v2', http=http)
54 token = OAuth2TokenFromCredentials(credentials).access_token
55 return http, token
56
57 # TODO(melandory): Functionality of _spredsheeet_for_logging belongs
58 # to websitetests, because this way we do not need to write results of run
59 # in separate file and then read it here.
60 def _spredsheeet_for_logging(sheet_key, access_token):
61 """ Connects to document where result of test run will be logged.
62 Args:
63 sheet_key: Key of sheet in Trix. Can be found in sheet's URL.
64 access_token: Access token of an account which should have edit rights.
65 """
66 # Connect to trix
67 service = SpreadsheetsService(additional_headers={
68 "Authorization": "Bearer " + access_token})
69 sheet = Sheet(service, sheet_key)
70 return sheet
71
72 def _try_run_individual_test(test_cmd, results_path):
73 """ Runs individual test and logs results to trix.
74
75 Args:
76 test_cmd: String contains command which runs test.
77 results_path: Full path to file where results of test run will be logged.
78 """
79 failures = []
80 # The tests can be flaky. This is why we try to rerun up to 3 times.
81 for x in xrange(3):
82 # TODO(rchtara): Using "pkill" is just temporary until a better,
83 # platform-independent solution is found.
84 # Using any kind of kill and process name isn't best solution.
85 # Mainly because it kills every running instace of Chrome on the machine,
86 # which is unpleasant experience, when you're running tests locally.
87 # In my opinion proper solution is to invoke chrome using subproceses and
88 # then kill only this particular instance of it.
89 os.system("pkill chrome")
90 try:
91 os.remove(results_path)
92 except Exception:
93 pass
94 # TODO(rchtara): Using "timeout is just temporary until a better,
95 # platform-independent solution is found.
96
97 # The website test runs in two passes, each pass has an internal
98 # timeout of 200s for waiting (see |remaining_time_to_wait| and
99 # Wait() in websitetest.py). Accounting for some more time spent on
100 # the non-waiting execution, 300 seconds should be the upper bound on
101 # the runtime of one pass, thus 600 seconds for the whole test.
102 # TODO(vabr): Use subprocess.call.
103 os.system("timeout 600 %s" % test_cmd)
104 if os.path.isfile(results_path):
105 results = open(results_path, "r")
106 count = 0 # Count the number of successful tests.
107 for line in results:
108 # TODO(melandory): We do not need to send all this data to sheet.
109 failures.append(line)
110 count += line.count("successful='True'")
111 results.close()
112 # There is only two tests running for every website: the prompt and
113 # the normal test. If both of the tests were successful, the tests
114 # would be stopped for the current website.
115 if count == 2:
116 return "pass", []
117 else:
118 pass
119 return "fail", failures
120
121
15 def run_tests( 122 def run_tests(
16 save_path, chrome_path, chromedriver_path, 123 chrome_path, chromedriver_path,
17 passwords_path, profile_path, *args, **kwargs): 124 profile_path, config_path, *args, **kwargs):
18 """ Runs automated tests. 125 """ Runs automated tests.
19 126
20 Args: 127 Args:
21 save_path: File, where results of run will be logged. 128 save_path: File, where results of run will be logged.
22 chrome_path: Location of Chrome binary. 129 chrome_path: Location of Chrome binary.
23 chromedriver_path: Location of Chrome Driver. 130 chromedriver_path: Location of Chrome Driver.
24 passwords_path: Location of file with credentials. 131 passwords_path: Location of file with credentials.
25 profile_path: Location of profile path. 132 profile_path: Location of profile path.
26 *args: Variable length argument list. 133 *args: Variable length argument list.
27 **kwargs: Arbitrary keyword arguments. 134 **kwargs: Arbitrary keyword arguments.
28 """ 135 """
29 environment = Environment('', '', '', None, False) 136 environment = Environment('', '', '', None, False)
30 tests.Tests(environment) 137 tests.Tests(environment)
31 138 config = ConfigParser.ConfigParser()
32 xml = open(save_path, "w") 139 config.read(config_path)
33 xml.write("<xml>") 140 date = datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
34 try: 141 try:
142 _, access_token = _authenticate(config.get("credentials", "pkey"),
143 config.get("credentials", "client_email"))
144 sheet = _spredsheeet_for_logging(config.get("drive", "key"), access_token)
35 results = tempfile.NamedTemporaryFile( 145 results = tempfile.NamedTemporaryFile(
36 dir=os.path.join(tempfile.gettempdir()), delete=False) 146 dir=os.path.join(tempfile.gettempdir()), delete=False)
37 results_path = results.name 147 results_path = results.name
38 results.close() 148 results.close()
39 149
40 full_path = os.path.realpath(__file__) 150 full_path = os.path.realpath(__file__)
41 tests_dir = os.path.dirname(full_path) 151 tests_dir = os.path.dirname(full_path)
42 tests_path = os.path.join(tests_dir, "tests.py") 152 tests_path = os.path.join(tests_dir, "tests.py")
43 153
44 for websitetest in environment.websitetests: 154 for websitetest in environment.websitetests:
45 # The tests can be flaky. This is why we try to rerun up to 3 times. 155 test_cmd = ("python %s %s --chrome-path %s "
46 for x in range(0, 3): 156 "--chromedriver-path %s"
47 # TODO(rchtara): Using "pkill" is just temporary until a better, 157 "--passwords-path %s --profile-path %s "
48 # platform-independent solution is found. 158 "--save-path %s" %
49 os.system("pkill chrome") 159 (tests_path, websitetest.name, chrome_path,
50 try: 160 chromedriver_path,
51 os.remove(results_path) 161 config.get("data_files", "passwords_path"),
52 except Exception: 162 profile_path, results_path))
53 pass 163 status, log = _try_run_individual_test(
54 # TODO(rchtara): Using "timeout is just temporary until a better, 164 websitetest, test_cmd, results_path)
55 # platform-independent solution is found. 165 try:
56 166 sheet.InsertRow(sheet.row_count,
57 # The website test runs in two passes, each pass has an internal 167 [websitetest.name, status, date, " | ".join(log)])
58 # timeout of 200s for waiting (see |remaining_time_to_wait| and 168 except Exception:
59 # Wait() in websitetest.py). Accounting for some more time spent on 169 pass # TODO(melandory): Sometimes writing to spreadsheet fails. We need
60 # the non-waiting execution, 300 seconds should be the upper bound on 170 # deal with it better that just ignoring.
61 # the runtime of one pass, thus 600 seconds for the whole test.
62 os.system("timeout 600 python %s %s --chrome-path %s "
63 "--chromedriver-path %s --passwords-path %s --profile-path %s "
64 "--save-path %s" %
65 (tests_path, websitetest.name, chrome_path,
66 chromedriver_path, passwords_path,
67 profile_path, results_path))
68 if os.path.isfile(results_path):
69 results = open(results_path, "r")
70 count = 0 # Count the number of successful tests.
71 for line in results:
72 xml.write(line)
73 count += line.count("successful='True'")
74 results.close()
75 # There is only two tests running for every website: the prompt and
76 # the normal test. If both of the tests were successful, the tests
77 # would be stopped for the current website.
78 if count == 2:
79 break
80 else:
81 xml.write("<result><test name='%s' type='prompt' successful='false'>"
82 "</test><test name='%s' type='normal' successful='false'></test>"
83 "</result>" % (websitetest.name, websitetest.name))
84 finally: 171 finally:
85 try: 172 try:
86 os.remove(results_path) 173 os.remove(results_path)
87 except Exception: 174 except Exception:
88 pass 175 pass
89 176
90 xml.write("</xml>")
91 xml.close()
92 177
93 if __name__ == "__main__": 178 if __name__ == "__main__":
94 parser = argparse.ArgumentParser( 179 parser = argparse.ArgumentParser(
95 description="Password Manager automated tests runner help.") 180 description="Password Manager automated tests runner help.")
96 parser.add_argument( 181 parser.add_argument(
97 "--chrome-path", action="store", dest="chrome_path", 182 "--chrome-path", action="store", dest="chrome_path",
98 help="Set the chrome path (required).", required=True) 183 help="Set the chrome path (required).", required=True)
99 parser.add_argument( 184 parser.add_argument(
100 "--chromedriver-path", action="store", dest="chromedriver_path", 185 "--chromedriver-path", action="store", dest="chromedriver_path",
101 help="Set the chromedriver path (required).", required=True) 186 help="Set the chromedriver path (required).", required=True)
102 parser.add_argument( 187 parser.add_argument(
188 "--config-path", action="store", dest="config_path",
189 help="File with configuration data: drive credentials, password path",
190 required=True)
191 parser.add_argument(
103 "--profile-path", action="store", dest="profile_path", 192 "--profile-path", action="store", dest="profile_path",
104 help="Set the profile path (required). You just need to choose a " 193 help="Set the profile path (required). You just need to choose a "
105 "temporary empty folder. If the folder is not empty all its content " 194 "temporary empty folder. If the folder is not empty all its content "
106 "is going to be removed.", 195 "is going to be removed.",
107 required=True) 196 required=True)
108 parser.add_argument(
109 "--passwords-path", action="store", dest="passwords_path",
110 help="Set the usernames/passwords path (required).", required=True)
111 parser.add_argument("--save-path", action="store", dest="save_path",
112 help="Write the results in a file.", required=True)
113 args = vars(parser.parse_args()) 197 args = vars(parser.parse_args())
114 run_tests(**args) 198 run_tests(**args)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698