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

Side by Side Diff: build/android/test_runner.py

Issue 19537004: [Android] Converts host driven tests to common test_dispatcher (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@sharding_refactoring
Patch Set: Converts --official-build into a boolean flag Created 7 years, 4 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 | « build/android/run_monkey_test.py ('k') | chrome/android/host_driven_tests/DummyTest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright 2013 The Chromium Authors. All rights reserved. 3 # Copyright 2013 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """Runs all types of tests from one unified interface. 7 """Runs all types of tests from one unified interface.
8 8
9 TODO(gkanwar): 9 TODO(gkanwar):
10 * Add options to run Monkey tests. 10 * Add options to run Monkey tests.
11 """ 11 """
12 12
13 import collections 13 import collections
14 import optparse 14 import optparse
15 import os 15 import os
16 import shutil 16 import shutil
17 import sys 17 import sys
18 18
19 from pylib import constants 19 from pylib import constants
20 from pylib import ports 20 from pylib import ports
21 from pylib.base import base_test_result 21 from pylib.base import base_test_result
22 from pylib.base import test_dispatcher 22 from pylib.base import test_dispatcher
23 from pylib.gtest import gtest_config 23 from pylib.gtest import gtest_config
24 from pylib.gtest import setup as gtest_setup 24 from pylib.gtest import setup as gtest_setup
25 from pylib.gtest import test_options as gtest_test_options 25 from pylib.gtest import test_options as gtest_test_options
26 from pylib.host_driven import run_python_tests as python_dispatch 26 from pylib.host_driven import setup as host_driven_setup
27 from pylib.instrumentation import setup as instrumentation_setup 27 from pylib.instrumentation import setup as instrumentation_setup
28 from pylib.instrumentation import test_options as instrumentation_test_options 28 from pylib.instrumentation import test_options as instrumentation_test_options
29 from pylib.uiautomator import setup as uiautomator_setup 29 from pylib.uiautomator import setup as uiautomator_setup
30 from pylib.uiautomator import test_options as uiautomator_test_options 30 from pylib.uiautomator import test_options as uiautomator_test_options
31 from pylib.utils import report_results 31 from pylib.utils import report_results
32 from pylib.utils import run_tests_helper 32 from pylib.utils import run_tests_helper
33 33
34 34
35 _SDK_OUT_DIR = os.path.join(constants.DIR_SOURCE_ROOT, 'out') 35 _SDK_OUT_DIR = os.path.join(constants.DIR_SOURCE_ROOT, 'out')
36 36
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 option_parser.add_option( 152 option_parser.add_option(
153 '-A', '--annotation', dest='annotation_str', 153 '-A', '--annotation', dest='annotation_str',
154 help=('Comma-separated list of annotations. Run only tests with any of ' 154 help=('Comma-separated list of annotations. Run only tests with any of '
155 'the given annotations. An annotation can be either a key or a ' 155 'the given annotations. An annotation can be either a key or a '
156 'key-values pair. A test that has no annotation is considered ' 156 'key-values pair. A test that has no annotation is considered '
157 '"SmallTest".')) 157 '"SmallTest".'))
158 option_parser.add_option( 158 option_parser.add_option(
159 '-E', '--exclude-annotation', dest='exclude_annotation_str', 159 '-E', '--exclude-annotation', dest='exclude_annotation_str',
160 help=('Comma-separated list of annotations. Exclude tests with these ' 160 help=('Comma-separated list of annotations. Exclude tests with these '
161 'annotations.')) 161 'annotations.'))
162 option_parser.add_option('-j', '--java_only', action='store_true',
163 default=False, help='Run only the Java tests.')
164 option_parser.add_option('-p', '--python_only', action='store_true',
165 default=False,
166 help='Run only the host-driven tests.')
167 option_parser.add_option('--screenshot', dest='screenshot_failures', 162 option_parser.add_option('--screenshot', dest='screenshot_failures',
168 action='store_true', 163 action='store_true',
169 help='Capture screenshots of test failures') 164 help='Capture screenshots of test failures')
170 option_parser.add_option('--save-perf-json', action='store_true', 165 option_parser.add_option('--save-perf-json', action='store_true',
171 help='Saves the JSON file for each UI Perf test.') 166 help='Saves the JSON file for each UI Perf test.')
172 option_parser.add_option('--official-build', help='Run official build tests.') 167 option_parser.add_option('--official-build', action='store_true',
173 option_parser.add_option('--python_test_root', 168 help='Run official build tests.')
174 help='Root of the host-driven tests.')
175 option_parser.add_option('--keep_test_server_ports', 169 option_parser.add_option('--keep_test_server_ports',
176 action='store_true', 170 action='store_true',
177 help=('Indicates the test server ports must be ' 171 help=('Indicates the test server ports must be '
178 'kept. When this is run via a sharder ' 172 'kept. When this is run via a sharder '
179 'the test server ports should be kept and ' 173 'the test server ports should be kept and '
180 'should not be reset.')) 174 'should not be reset.'))
181 # TODO(gkanwar): This option is deprecated. Remove it in the future. 175 # TODO(gkanwar): This option is deprecated. Remove it in the future.
182 option_parser.add_option('--disable_assertions', action='store_true', 176 option_parser.add_option('--disable_assertions', action='store_true',
183 help=('(DEPRECATED) Run with java assertions ' 177 help=('(DEPRECATED) Run with java assertions '
184 'disabled.')) 178 'disabled.'))
185 option_parser.add_option('--test_data', action='append', default=[], 179 option_parser.add_option('--test_data', action='append', default=[],
186 help=('Each instance defines a directory of test ' 180 help=('Each instance defines a directory of test '
187 'data that should be copied to the target(s) ' 181 'data that should be copied to the target(s) '
188 'before running the tests. The argument ' 182 'before running the tests. The argument '
189 'should be of the form <target>:<source>, ' 183 'should be of the form <target>:<source>, '
190 '<target> is relative to the device data' 184 '<target> is relative to the device data'
191 'directory, and <source> is relative to the ' 185 'directory, and <source> is relative to the '
192 'chromium build directory.')) 186 'chromium build directory.'))
193 187
194 188
195 def ProcessJavaTestOptions(options, error_func): 189 def ProcessJavaTestOptions(options, error_func):
196 """Processes options/arguments and populates |options| with defaults.""" 190 """Processes options/arguments and populates |options| with defaults."""
197 191
198 if options.java_only and options.python_only:
199 error_func('Options java_only (-j) and python_only (-p) '
200 'are mutually exclusive.')
201 options.run_java_tests = True
202 options.run_python_tests = True
203 if options.java_only:
204 options.run_python_tests = False
205 elif options.python_only:
206 options.run_java_tests = False
207
208 if not options.python_test_root:
209 options.run_python_tests = False
210
211 if options.annotation_str: 192 if options.annotation_str:
212 options.annotations = options.annotation_str.split(',') 193 options.annotations = options.annotation_str.split(',')
213 elif options.test_filter: 194 elif options.test_filter:
214 options.annotations = [] 195 options.annotations = []
215 else: 196 else:
216 options.annotations = ['Smoke', 'SmallTest', 'MediumTest', 'LargeTest', 197 options.annotations = ['Smoke', 'SmallTest', 'MediumTest', 'LargeTest',
217 'EnormousTest'] 198 'EnormousTest']
218 199
219 if options.exclude_annotation_str: 200 if options.exclude_annotation_str:
220 options.exclude_annotations = options.exclude_annotation_str.split(',') 201 options.exclude_annotations = options.exclude_annotation_str.split(',')
221 else: 202 else:
222 options.exclude_annotations = [] 203 options.exclude_annotations = []
223 204
224 if not options.keep_test_server_ports: 205 if not options.keep_test_server_ports:
225 if not ports.ResetTestServerPortAllocation(): 206 if not ports.ResetTestServerPortAllocation():
226 raise Exception('Failed to reset test server port.') 207 raise Exception('Failed to reset test server port.')
227 208
228 209
229 def AddInstrumentationTestOptions(option_parser): 210 def AddInstrumentationTestOptions(option_parser):
230 """Adds Instrumentation test options to |option_parser|.""" 211 """Adds Instrumentation test options to |option_parser|."""
231 212
232 option_parser.usage = '%prog instrumentation [options]' 213 option_parser.usage = '%prog instrumentation [options]'
233 option_parser.command_list = [] 214 option_parser.command_list = []
234 option_parser.example = ('%prog instrumentation ' 215 option_parser.example = ('%prog instrumentation '
235 '--test-apk=ChromiumTestShellTest') 216 '--test-apk=ChromiumTestShellTest')
236 217
237 AddJavaTestOptions(option_parser) 218 AddJavaTestOptions(option_parser)
238 AddCommonOptions(option_parser) 219 AddCommonOptions(option_parser)
239 220
221 option_parser.add_option('-j', '--java_only', action='store_true',
222 default=False, help='Run only the Java tests.')
223 option_parser.add_option('-p', '--python_only', action='store_true',
224 default=False,
225 help='Run only the host-driven tests.')
226 option_parser.add_option('--python_test_root',
227 help='Root of the host-driven tests.')
240 option_parser.add_option('-w', '--wait_debugger', dest='wait_for_debugger', 228 option_parser.add_option('-w', '--wait_debugger', dest='wait_for_debugger',
241 action='store_true', 229 action='store_true',
242 help='Wait for debugger.') 230 help='Wait for debugger.')
243 #TODO(craigdh): Remove option once -I is no longer passed downstream. 231 #TODO(craigdh): Remove option once -I is no longer passed downstream.
244 option_parser.add_option('-I', dest='install_apk', action='store_true', 232 option_parser.add_option('-I', dest='install_apk', action='store_true',
245 help='(DEPRECATED) Install the test apk.') 233 help='(DEPRECATED) Install the test apk.')
246 option_parser.add_option( 234 option_parser.add_option(
247 '--test-apk', dest='test_apk', 235 '--test-apk', dest='test_apk',
248 help=('The name of the apk containing the tests ' 236 help=('The name of the apk containing the tests '
249 '(without the .apk extension; e.g. "ContentShellTest"). ' 237 '(without the .apk extension; e.g. "ContentShellTest"). '
250 'Alternatively, this can be a full path to the apk.')) 238 'Alternatively, this can be a full path to the apk.'))
251 239
252 240
253 def ProcessInstrumentationOptions(options, error_func): 241 def ProcessInstrumentationOptions(options, error_func):
254 """Processes options/arguments and populate |options| with defaults. 242 """Processes options/arguments and populate |options| with defaults.
255 243
256 Args: 244 Args:
257 options: optparse.Options object. 245 options: optparse.Options object.
258 error_func: Function to call with the error message in case of an error. 246 error_func: Function to call with the error message in case of an error.
259 247
260 Returns: 248 Returns:
261 An InstrumentationOptions named tuple which contains all options relevant to 249 An InstrumentationOptions named tuple which contains all options relevant to
262 instrumentation tests. 250 instrumentation tests.
263 """ 251 """
264 252
265 ProcessJavaTestOptions(options, error_func) 253 ProcessJavaTestOptions(options, error_func)
266 254
255 if options.java_only and options.python_only:
256 error_func('Options java_only (-j) and python_only (-p) '
257 'are mutually exclusive.')
258 options.run_java_tests = True
259 options.run_python_tests = True
260 if options.java_only:
261 options.run_python_tests = False
262 elif options.python_only:
263 options.run_java_tests = False
264
265 if not options.python_test_root:
266 options.run_python_tests = False
267
267 if not options.test_apk: 268 if not options.test_apk:
268 error_func('--test-apk must be specified.') 269 error_func('--test-apk must be specified.')
269 270
270 if os.path.exists(options.test_apk): 271 if os.path.exists(options.test_apk):
271 # The APK is fully qualified, assume the JAR lives along side. 272 # The APK is fully qualified, assume the JAR lives along side.
272 options.test_apk_path = options.test_apk 273 options.test_apk_path = options.test_apk
273 options.test_apk_jar_path = (os.path.splitext(options.test_apk_path)[0] + 274 options.test_apk_jar_path = (os.path.splitext(options.test_apk_path)[0] +
274 '.jar') 275 '.jar')
275 else: 276 else:
276 options.test_apk_path = os.path.join(_SDK_OUT_DIR, 277 options.test_apk_path = os.path.join(_SDK_OUT_DIR,
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 tests, runner_factory, options.wait_for_debugger, 425 tests, runner_factory, options.wait_for_debugger,
425 options.test_device, 426 options.test_device,
426 shard=True, 427 shard=True,
427 build_type=options.build_type, 428 build_type=options.build_type,
428 test_timeout=None, 429 test_timeout=None,
429 num_retries=options.num_retries) 430 num_retries=options.num_retries)
430 431
431 results.AddTestRunResults(test_results) 432 results.AddTestRunResults(test_results)
432 433
433 if options.run_python_tests: 434 if options.run_python_tests:
434 test_results, test_exit_code = ( 435 runner_factory, tests = host_driven_setup.InstrumentationSetup(
435 python_dispatch.DispatchPythonTests(options)) 436 options.python_test_root, options.official_build,
437 instrumentation_options)
438
439 test_results, test_exit_code = test_dispatcher.RunTests(
440 tests, runner_factory, False,
441 options.test_device,
442 shard=True,
443 build_type=options.build_type,
444 test_timeout=None,
445 num_retries=options.num_retries)
436 446
437 results.AddTestRunResults(test_results) 447 results.AddTestRunResults(test_results)
438 448
439 # Only allow exit code escalation 449 # Only allow exit code escalation
440 if test_exit_code and exit_code != constants.ERROR_EXIT_CODE: 450 if test_exit_code and exit_code != constants.ERROR_EXIT_CODE:
441 exit_code = test_exit_code 451 exit_code = test_exit_code
442 452
443 report_results.LogFull( 453 report_results.LogFull(
444 results=results, 454 results=results,
445 test_type='Instrumentation', 455 test_type='Instrumentation',
446 test_package=os.path.basename(options.test_apk), 456 test_package=os.path.basename(options.test_apk),
447 annotation=options.annotations, 457 annotation=options.annotations,
448 build_type=options.build_type, 458 build_type=options.build_type,
449 flakiness_server=options.flakiness_dashboard_server) 459 flakiness_server=options.flakiness_dashboard_server)
450 460
451 return exit_code 461 return exit_code
452 462
453 463
454 def _RunUIAutomatorTests(options, error_func): 464 def _RunUIAutomatorTests(options, error_func):
455 """Subcommand of RunTestsCommands which runs uiautomator tests.""" 465 """Subcommand of RunTestsCommands which runs uiautomator tests."""
456 uiautomator_options = ProcessUIAutomatorOptions(options, error_func) 466 uiautomator_options = ProcessUIAutomatorOptions(options, error_func)
457 467
458 results = base_test_result.TestRunResults() 468 results = base_test_result.TestRunResults()
459 exit_code = 0 469 exit_code = 0
460 470
461 if options.run_java_tests: 471 runner_factory, tests = uiautomator_setup.Setup(uiautomator_options)
462 runner_factory, tests = uiautomator_setup.Setup(uiautomator_options)
463 472
464 test_results, exit_code = test_dispatcher.RunTests( 473 results, exit_code = test_dispatcher.RunTests(
465 tests, runner_factory, False, options.test_device, 474 tests, runner_factory, False, options.test_device,
466 shard=True, 475 shard=True,
467 build_type=options.build_type, 476 build_type=options.build_type,
468 test_timeout=None, 477 test_timeout=None,
469 num_retries=options.num_retries) 478 num_retries=options.num_retries)
470
471 results.AddTestRunResults(test_results)
472
473 if options.run_python_tests:
474 test_results, test_exit_code = (
475 python_dispatch.DispatchPythonTests(options))
476
477 results.AddTestRunResults(test_results)
478
479 # Only allow exit code escalation
480 if test_exit_code and exit_code != constants.ERROR_EXIT_CODE:
481 exit_code = test_exit_code
482 479
483 report_results.LogFull( 480 report_results.LogFull(
484 results=results, 481 results=results,
485 test_type='UIAutomator', 482 test_type='UIAutomator',
486 test_package=os.path.basename(options.test_jar), 483 test_package=os.path.basename(options.test_jar),
487 annotation=options.annotations, 484 annotation=options.annotations,
488 build_type=options.build_type, 485 build_type=options.build_type,
489 flakiness_server=options.flakiness_dashboard_server) 486 flakiness_server=options.flakiness_dashboard_server)
490 487
491 return exit_code 488 return exit_code
(...skipping 26 matching lines...) Expand all
518 515
519 if command == 'gtest': 516 if command == 'gtest':
520 return _RunGTests(options, option_parser.error) 517 return _RunGTests(options, option_parser.error)
521 elif command == 'instrumentation': 518 elif command == 'instrumentation':
522 return _RunInstrumentationTests(options, option_parser.error) 519 return _RunInstrumentationTests(options, option_parser.error)
523 elif command == 'uiautomator': 520 elif command == 'uiautomator':
524 return _RunUIAutomatorTests(options, option_parser.error) 521 return _RunUIAutomatorTests(options, option_parser.error)
525 else: 522 else:
526 raise Exception('Unknown test type.') 523 raise Exception('Unknown test type.')
527 524
528 return exit_code
529
530 525
531 def HelpCommand(command, options, args, option_parser): 526 def HelpCommand(command, options, args, option_parser):
532 """Display help for a certain command, or overall help. 527 """Display help for a certain command, or overall help.
533 528
534 Args: 529 Args:
535 command: String indicating the command that was received to trigger 530 command: String indicating the command that was received to trigger
536 this function. 531 this function.
537 options: optparse options dictionary. 532 options: optparse options dictionary.
538 args: List of extra args from optparse. 533 args: List of extra args from optparse.
539 option_parser: optparse.OptionParser object. 534 option_parser: optparse.OptionParser object.
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 return 0 616 return 0
622 command = argv[1] 617 command = argv[1]
623 VALID_COMMANDS[command].add_options_func(option_parser) 618 VALID_COMMANDS[command].add_options_func(option_parser)
624 options, args = option_parser.parse_args(argv) 619 options, args = option_parser.parse_args(argv)
625 return VALID_COMMANDS[command].run_command_func( 620 return VALID_COMMANDS[command].run_command_func(
626 command, options, args, option_parser) 621 command, options, args, option_parser)
627 622
628 623
629 if __name__ == '__main__': 624 if __name__ == '__main__':
630 sys.exit(main(sys.argv)) 625 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « build/android/run_monkey_test.py ('k') | chrome/android/host_driven_tests/DummyTest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698