OLD | NEW |
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 configured and run the tests. |
7 | 7 |
8 Running this script requires passing --config-path with a path to a config file | 8 Running this script requires passing --config-path with a path to a config file |
9 of the following structure: | 9 of the following structure: |
| 10 |
10 [data_files] | 11 [data_files] |
11 passwords_path=<path to a file with passwords> | 12 passwords_path=<path to a file with passwords> |
12 [binaries] | 13 [binaries] |
13 chrome-path=<chrome binary path> | 14 chrome-path=<chrome binary path> |
14 chromedriver-path=<chrome driver path> | 15 chromedriver-path=<chrome driver path> |
15 [run_options] | 16 [run_options] |
| 17 # |write_to_sheet| is optional, the default value is false. |
16 write_to_sheet=[false|true] | 18 write_to_sheet=[false|true] |
17 tests_in_parrallel=<number of parallel tests> | 19 # |tests_in_parallel| is optional, the default value is 1. |
| 20 tests_in_parallel=<number of parallel tests> |
18 # |tests_to_runs| field is optional, if it is absent all tests will be run. | 21 # |tests_to_runs| field is optional, if it is absent all tests will be run. |
19 tests_to_run=<test names to run, comma delimited> | 22 tests_to_run=<test names to run, comma delimited> |
20 [output] | 23 [output] |
| 24 # |save-path| is optional, the default value is /dev/null. |
21 save-path=<file where to save result> | 25 save-path=<file where to save result> |
22 [sheet_info] | 26 [sheet_info] |
23 # This section is required only when write_to_sheet=true | 27 # This section is required only when write_to_sheet=true |
24 pkey=full_path | 28 pkey=full_path |
25 client_email=email_assigned_by_google_dev_console | 29 client_email=email_assigned_by_google_dev_console |
26 sheet_key=sheet_key_from_sheet_url | 30 sheet_key=sheet_key_from_sheet_url |
27 """ | 31 """ |
28 from datetime import datetime | 32 from datetime import datetime |
29 import ConfigParser | 33 import ConfigParser |
30 import sys | 34 import sys |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 except Exception: | 174 except Exception: |
171 pass | 175 pass |
172 try: | 176 try: |
173 shutil.rmtree(self.profile_path) | 177 shutil.rmtree(self.profile_path) |
174 except Exception: | 178 except Exception: |
175 pass | 179 pass |
176 self.max_test_runs_left -= 1 | 180 self.max_test_runs_left -= 1 |
177 print "Run of test %s started" % self.test_name | 181 print "Run of test %s started" % self.test_name |
178 self.runner_process = subprocess.Popen(self.test_cmd) | 182 self.runner_process = subprocess.Popen(self.test_cmd) |
179 | 183 |
| 184 def _apply_defaults(config, defaults): |
| 185 """Adds default values from |defaults| to |config|. |
| 186 |
| 187 Note: This differs from ConfigParser's mechanism for providing defaults in |
| 188 two aspects: |
| 189 * The "defaults" here become explicit, and are associated with sections. |
| 190 * Sections get created for the added defaults where needed, that is, if |
| 191 they do not exist before. |
| 192 |
| 193 Args: |
| 194 config: A ConfigParser instance to be updated |
| 195 defaults: A dictionary mapping (section_string, option_string) pairs |
| 196 to string values. For every section/option combination not already |
| 197 contained in |config|, the value from |defaults| is stored in |config|. |
| 198 """ |
| 199 for (section, option) in defaults: |
| 200 if not config.has_section(section): |
| 201 config.add_section(section) |
| 202 if not config.has_option(section, option): |
| 203 config.set(section, option, defaults[(section, option)]) |
| 204 |
180 def run_tests(config_path): | 205 def run_tests(config_path): |
181 """ Runs automated tests. """ | 206 """ Runs automated tests. """ |
182 environment = Environment("", "", "", None, False) | 207 environment = Environment("", "", "", None, False) |
183 tests.Tests(environment) | 208 tests.Tests(environment) |
| 209 defaults = { ("output", "save-path"): "/dev/null", |
| 210 ("run_options", "tests_in_parallel"): "1", |
| 211 ("run_options", "write_to_sheet"): "false" } |
184 config = ConfigParser.ConfigParser() | 212 config = ConfigParser.ConfigParser() |
| 213 _apply_defaults(config, defaults) |
185 config.read(config_path) | 214 config.read(config_path) |
186 date = datetime.now().strftime('%Y-%m-%dT%H:%M:%S') | 215 date = datetime.now().strftime('%Y-%m-%dT%H:%M:%S') |
187 max_tests_in_parrallel = config.getint("run_options", "tests_in_parrallel") | 216 max_tests_in_parallel = config.getint("run_options", "tests_in_parallel") |
188 sheet_writer = SheetWriter(config) | 217 sheet_writer = SheetWriter(config) |
189 full_path = os.path.realpath(__file__) | 218 full_path = os.path.realpath(__file__) |
190 tests_dir = os.path.dirname(full_path) | 219 tests_dir = os.path.dirname(full_path) |
191 tests_path = os.path.join(tests_dir, "tests.py") | 220 tests_path = os.path.join(tests_dir, "tests.py") |
192 general_test_cmd = ["python", tests_path, "test_name_placeholder", | 221 general_test_cmd = ["python", tests_path, "test_name_placeholder", |
193 "--chrome-path", config.get("binaries", "chrome-path"), | 222 "--chrome-path", config.get("binaries", "chrome-path"), |
194 "--chromedriver-path", config.get("binaries", "chromedriver-path"), | 223 "--chromedriver-path", config.get("binaries", "chromedriver-path"), |
195 "--passwords-path", config.get("data_files", "passwords_path")] | 224 "--passwords-path", config.get("data_files", "passwords_path")] |
196 runners = [] | 225 runners = [] |
197 tests_to_run = [test.name for test in environment.websitetests] | 226 tests_to_run = [test.name for test in environment.websitetests] |
198 if config.has_option("run_options", "tests_to_run"): | 227 if config.has_option("run_options", "tests_to_run"): |
199 user_selected_tests = config.get("run_options", "tests_to_run").split(',') | 228 user_selected_tests = config.get("run_options", "tests_to_run").split(',') |
200 # TODO((dvadym) Validate the user selected tests are available. | 229 # TODO((dvadym) Validate the user selected tests are available. |
201 tests_to_run = list(set(tests_to_run) & set(user_selected_tests)) | 230 tests_to_run = list(set(tests_to_run) & set(user_selected_tests)) |
202 | 231 |
203 with open(config.get("output", "save-path"), 'w') as savefile: | 232 with open(config.get("output", "save-path"), 'w') as savefile: |
204 print "Tests to run %d\nTests: %s" % (len(tests_to_run), tests_to_run) | 233 print "Tests to run %d\nTests: %s" % (len(tests_to_run), tests_to_run) |
205 while len(runners) + len(tests_to_run) > 0: | 234 while len(runners) + len(tests_to_run) > 0: |
206 i = 0 | 235 i = 0 |
207 while i < len(runners): | 236 while i < len(runners): |
208 result = runners[i].get_test_result() | 237 result = runners[i].get_test_result() |
209 if result: # This test run is finished. | 238 if result: # This test run is finished. |
210 status, log = result | 239 status, log = result |
211 testinfo = [runners[i].test_name, status, date, " | ".join(log)] | 240 testinfo = [runners[i].test_name, status, date, " | ".join(log)] |
212 sheet_writer.write_line_to_sheet(testinfo) | 241 sheet_writer.write_line_to_sheet(testinfo) |
213 print>>savefile, " ".join(testinfo) | 242 print>>savefile, " ".join(testinfo) |
214 del runners[i] | 243 del runners[i] |
215 else: | 244 else: |
216 i += 1 | 245 i += 1 |
217 while len(runners) < max_tests_in_parrallel and len(tests_to_run) > 0: | 246 while len(runners) < max_tests_in_parallel and len(tests_to_run) > 0: |
218 runners.append(TestRunner(general_test_cmd, tests_to_run.pop())) | 247 runners.append(TestRunner(general_test_cmd, tests_to_run.pop())) |
219 time.sleep(1) # Let us wait for worker process to finish. | 248 time.sleep(1) # Let us wait for worker process to finish. |
220 | 249 |
221 if __name__ == "__main__": | 250 if __name__ == "__main__": |
222 if len(sys.argv) != 2: | 251 if len(sys.argv) != 2: |
223 print "Synopsis:\n python run_tests.py <config_path>" | 252 print "Synopsis:\n python run_tests.py <config_path>" |
224 config_path = sys.argv[1] | 253 config_path = sys.argv[1] |
225 run_tests(config_path) | 254 run_tests(config_path) |
OLD | NEW |