OLD | NEW |
---|---|
1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import argparse | 5 import argparse |
6 import json | 6 import json |
7 import logging | 7 import logging |
8 import os | 8 import os |
9 import re | 9 import re |
10 import socket | 10 import socket |
11 import shlex | 11 import shlex |
12 import sys | 12 import sys |
13 import time | 13 import time |
14 import traceback | 14 import traceback |
15 import unittest | 15 import unittest |
16 import urlparse | 16 import urlparse |
17 | 17 |
18 sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, | 18 sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, |
19 os.pardir, 'third_party', 'webdriver', 'pylib')) | 19 os.pardir, 'third_party', 'webdriver', 'pylib')) |
20 from selenium import webdriver | 20 from selenium import webdriver |
21 from selenium.webdriver.chrome.options import Options | 21 from selenium.webdriver.chrome.options import Options |
22 | 22 |
23 def ParseFlags(): | 23 def ParseFlags(): |
24 """Parses the given command line arguments. | 24 """Parses the given command line arguments. |
25 | 25 |
26 Returns: | 26 Returns: |
27 A new Namespace object with class properties for each argument added below. | 27 A new Namespace object with class properties for each argument added below. |
28 See pydoc for argparse. | 28 See pydoc for argparse. |
29 """ | 29 """ |
30 def TestFilter(v): | |
31 try: | |
32 # The filtering here allows for any number of * wildcards with a required | |
33 # . separator between classname and methodname, but no other special | |
34 # characters. | |
35 return re.match('^[A-Za-z_0-9\*]+\.[A-Za-z_0-9\*]+$', v).group(0) | |
RyanSturm
2017/01/11 17:42:10
This should accept TestClass* in addition to TestC
Robert Ogden
2017/01/11 19:19:44
Took the first option. It seems cleaner to me.
| |
36 except: | |
37 raise argparse.ArgumentTypeError('Test filter "%s" is not a valid filter' | |
38 % v) | |
30 parser = argparse.ArgumentParser() | 39 parser = argparse.ArgumentParser() |
31 parser.add_argument('--browser_args', type=str, help='Override browser flags ' | 40 parser.add_argument('--browser_args', type=str, help='Override browser flags ' |
32 'in code with these flags') | 41 'in code with these flags') |
33 parser.add_argument('--via_header_value', | 42 parser.add_argument('--via_header_value', |
34 default='1.1 Chrome-Compression-Proxy', help='What the via should match to ' | 43 default='1.1 Chrome-Compression-Proxy', help='What the via should match to ' |
35 'be considered valid') | 44 'be considered valid') |
36 parser.add_argument('--android', help='If given, attempts to run the test on ' | 45 parser.add_argument('--android', help='If given, attempts to run the test on ' |
37 'Android via adb. Ignores usage of --chrome_exec', action='store_true') | 46 'Android via adb. Ignores usage of --chrome_exec', action='store_true') |
38 parser.add_argument('--android_package', | 47 parser.add_argument('--android_package', |
39 default='com.android.chrome', help='Set the android package for Chrome') | 48 default='com.android.chrome', help='Set the android package for Chrome') |
40 parser.add_argument('--chrome_exec', type=str, help='The path to ' | 49 parser.add_argument('--chrome_exec', type=str, help='The path to ' |
41 'the Chrome or Chromium executable') | 50 'the Chrome or Chromium executable') |
42 parser.add_argument('chrome_driver', type=str, help='The path to ' | 51 parser.add_argument('chrome_driver', type=str, help='The path to ' |
43 'the ChromeDriver executable. If not given, the default system chrome ' | 52 'the ChromeDriver executable. If not given, the default system chrome ' |
44 'will be used.') | 53 'will be used.') |
45 parser.add_argument('--disable_buffer', help='Causes stdout and stderr from ' | 54 parser.add_argument('--disable_buffer', help='Causes stdout and stderr from ' |
46 'tests to output normally. Otherwise, the standard output and standard ' | 55 'tests to output normally. Otherwise, the standard output and standard ' |
47 'error streams are buffered during the test run, and output from a ' | 56 'error streams are buffered during the test run, and output from a ' |
48 'passing test is discarded. Output will always be echoed normally on test ' | 57 'passing test is discarded. Output will always be echoed normally on test ' |
49 'fail or error and is added to the failure messages.', action='store_true') | 58 'fail or error and is added to the failure messages.', action='store_true') |
50 parser.add_argument('-c', '--catch', help='Control-C during the test run ' | 59 parser.add_argument('-c', '--catch', help='Control-C during the test run ' |
51 'waits for the current test to end and then reports all the results so ' | 60 'waits for the current test to end and then reports all the results so ' |
52 'far. A second Control-C raises the normal KeyboardInterrupt exception.', | 61 'far. A second Control-C raises the normal KeyboardInterrupt exception.', |
53 action='store_true') | 62 action='store_true') |
54 parser.add_argument('-f', '--failfast', help='Stop the test run on the first ' | 63 parser.add_argument('-f', '--failfast', help='Stop the test run on the first ' |
55 'error or failure.', action='store_true') | 64 'error or failure.', action='store_true') |
65 parser.add_argument('--test_filter', '--gtest_filter', type=TestFilter, | |
66 help='The filter to use when discovering tests to run, in the form ' | |
67 '<class name>.<method name> Wildcards (*) are accepted. Default=*.*', | |
68 default='*.test*') | |
56 parser.add_argument('--logging_level', choices=['DEBUG', 'INFO', 'WARN', | 69 parser.add_argument('--logging_level', choices=['DEBUG', 'INFO', 'WARN', |
57 'ERROR', 'CRIT'], default='WARN', help='The logging verbosity for log ' | 70 'ERROR', 'CRIT'], default='WARN', help='The logging verbosity for log ' |
58 'messages, printed to stderr. To see stderr logging output during a ' | 71 'messages, printed to stderr. To see stderr logging output during a ' |
59 'successful test run, also pass --disable_buffer. Default=ERROR') | 72 'successful test run, also pass --disable_buffer. Default=ERROR') |
60 parser.add_argument('--log_file', help='If given, write logging statements ' | 73 parser.add_argument('--log_file', help='If given, write logging statements ' |
61 'to the given file instead of stderr.') | 74 'to the given file instead of stderr.') |
62 return parser.parse_args(sys.argv[1:]) | 75 return parser.parse_args(sys.argv[1:]) |
63 | 76 |
64 def GetLogger(name='common'): | 77 def GetLogger(name='common'): |
65 """Creates a Logger instance with the given name and returns it. | 78 """Creates a Logger instance with the given name and returns it. |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
533 Args: | 546 Args: |
534 run_all_tests: If True, all tests in the directory will be run, Otherwise | 547 run_all_tests: If True, all tests in the directory will be run, Otherwise |
535 only the tests in the file given on the command line will be run. | 548 only the tests in the file given on the command line will be run. |
536 """ | 549 """ |
537 flags = ParseFlags() | 550 flags = ParseFlags() |
538 logger = GetLogger() | 551 logger = GetLogger() |
539 logger.debug('Command line args: %s', str(sys.argv)) | 552 logger.debug('Command line args: %s', str(sys.argv)) |
540 logger.info('sys.argv parsed to %s', str(flags)) | 553 logger.info('sys.argv parsed to %s', str(flags)) |
541 if flags.catch: | 554 if flags.catch: |
542 unittest.installHandler() | 555 unittest.installHandler() |
556 # Use python's test discovery to locate tests files that have subclasses of | |
557 # unittest.TestCase and methods beginning with 'test'. | |
543 pattern = '*.py' if run_all_tests else os.path.basename(sys.argv[0]) | 558 pattern = '*.py' if run_all_tests else os.path.basename(sys.argv[0]) |
544 loader = unittest.TestLoader() | 559 loader = unittest.TestLoader() |
545 tests = loader.discover(os.path.dirname(__file__), pattern=pattern) | 560 test_suite_iter = loader.discover(os.path.dirname(__file__), |
561 pattern=pattern) | |
562 # Match class and method name on the given test filter from --test_filter. | |
563 tests = unittest.TestSuite() | |
564 test_filter_re = flags.test_filter.replace('.', r'\.').replace('*', '.*') | |
RyanSturm
2017/01/11 17:42:10
See comment above. I think if you do the last appr
Robert Ogden
2017/01/11 19:19:44
Acknowledged.
| |
565 for test_suite in test_suite_iter: | |
566 for test_case in test_suite: | |
567 for test in test_case: | |
568 # Drop the file name in the form <filename>.<classname>.<methodname> | |
569 test_id = test.id()[test.id().find('.') + 1:] | |
570 if re.match(test_filter_re, test_id): | |
571 tests.addTest(test) | |
546 testRunner = unittest.runner.TextTestRunner(verbosity=2, | 572 testRunner = unittest.runner.TextTestRunner(verbosity=2, |
547 failfast=flags.failfast, buffer=(not flags.disable_buffer)) | 573 failfast=flags.failfast, buffer=(not flags.disable_buffer)) |
548 testRunner.run(tests) | 574 testRunner.run(tests) |
OLD | NEW |