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

Unified Diff: tools/telemetry/telemetry/unittest/run_tests.py

Issue 659293003: Switch telemetry over to use typ to run the unit tests. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@rev_typ_v086
Patch Set: fix merge error in browser_test_case Created 6 years, 1 month 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: tools/telemetry/telemetry/unittest/run_tests.py
diff --git a/tools/telemetry/telemetry/unittest/run_tests.py b/tools/telemetry/telemetry/unittest/run_tests.py
index de825d27986eebf83bdbcc3e27918b1495404b9c..1a827a9207155ff2f2a9476840ae102401e4be3c 100644
--- a/tools/telemetry/telemetry/unittest/run_tests.py
+++ b/tools/telemetry/telemetry/unittest/run_tests.py
@@ -1,114 +1,19 @@
# Copyright 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
-import logging
-import unittest
+import sys
from telemetry import decorators
from telemetry.core import browser_finder
from telemetry.core import browser_options
from telemetry.core import command_line
-from telemetry.core import discover
-from telemetry.unittest import json_results
-from telemetry.unittest import progress_reporter
-
-
-class Config(object):
- def __init__(self, top_level_dir, test_dirs, progress_reporters):
- self._top_level_dir = top_level_dir
- self._test_dirs = tuple(test_dirs)
- self._progress_reporters = tuple(progress_reporters)
-
- @property
- def top_level_dir(self):
- return self._top_level_dir
-
- @property
- def test_dirs(self):
- return self._test_dirs
-
- @property
- def progress_reporters(self):
- return self._progress_reporters
-
-
-def Discover(start_dir, top_level_dir=None, pattern='test*.py'):
- loader = unittest.defaultTestLoader
- loader.suiteClass = progress_reporter.TestSuite
-
- test_suites = []
- modules = discover.DiscoverModules(start_dir, top_level_dir, pattern)
- for module in modules:
- if hasattr(module, 'suite'):
- suite = module.suite()
- else:
- suite = loader.loadTestsFromModule(module)
- if suite.countTestCases():
- test_suites.append(suite)
- return test_suites
-
-
-def FilterSuite(suite, predicate):
- new_suite = suite.__class__()
- for test in suite:
- if isinstance(test, unittest.TestSuite):
- subsuite = FilterSuite(test, predicate)
- if subsuite.countTestCases():
- new_suite.addTest(subsuite)
- else:
- assert isinstance(test, unittest.TestCase)
- if predicate(test):
- new_suite.addTest(test)
-
- return new_suite
-
-
-def DiscoverTests(search_dirs, top_level_dir, possible_browser,
- selected_tests=None, selected_tests_are_exact=False,
- run_disabled_tests=False):
- def IsTestSelected(test):
- if selected_tests:
- found = False
- for name in selected_tests:
- if selected_tests_are_exact:
- if name == test.id():
- found = True
- else:
- if name in test.id():
- found = True
- if not found:
- return False
- if run_disabled_tests:
- return True
- # pylint: disable=W0212
- if not hasattr(test, '_testMethodName'):
- return True
- method = getattr(test, test._testMethodName)
- return decorators.IsEnabled(method, possible_browser)
-
- wrapper_suite = progress_reporter.TestSuite()
- for search_dir in search_dirs:
- wrapper_suite.addTests(Discover(search_dir, top_level_dir, '*_unittest.py'))
- return FilterSuite(wrapper_suite, IsTestSelected)
-
-
-def RestoreLoggingLevel(func):
- def _LoggingRestoreWrapper(*args, **kwargs):
- # Cache the current logging level, this needs to be done before calling
- # parser.parse_args, which changes logging level based on verbosity
- # setting.
- logging_level = logging.getLogger().getEffectiveLevel()
- try:
- return func(*args, **kwargs)
- finally:
- # Restore logging level, which may be changed in parser.parse_args.
- logging.getLogger().setLevel(logging_level)
-
- return _LoggingRestoreWrapper
+from telemetry.core import util
+from telemetry.unittest import options_for_unittests
+from telemetry.unittest import browser_test_case
+util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'third_party', 'typ')
-config = None
+import typ
class RunTestsCommand(command_line.OptparseCommand):
@@ -116,6 +21,10 @@ class RunTestsCommand(command_line.OptparseCommand):
usage = '[test_name ...] [<options>]'
+ def __init__(self):
+ super(RunTestsCommand, self).__init__()
+ self.stream = sys.stdout
+
@classmethod
def CreateParser(cls):
options = browser_options.BrowserFinderOptions()
@@ -131,22 +40,24 @@ class RunTestsCommand(command_line.OptparseCommand):
dest='run_disabled_tests',
action='store_true', default=False,
help='Ignore @Disabled and @Enabled restrictions.')
- parser.add_option('--retry-limit', type='int',
- help='Retry each failure up to N times'
- ' to de-flake things.')
parser.add_option('--exact-test-filter', action='store_true', default=False,
help='Treat test filter as exact matches (default is '
'substring matches).')
- json_results.AddOptions(parser)
+
+ typ.ArgumentParser.add_option_group(parser,
+ "Options for running the tests",
+ running=True,
+ skip=['-d', '--path', '-v',
+ '--verbose'])
+ typ.ArgumentParser.add_option_group(parser,
+ "Options for reporting the results",
+ reporting=True)
@classmethod
def ProcessCommandLineArgs(cls, parser, args):
- if args.verbosity == 0:
- logging.getLogger().setLevel(logging.WARN)
-
# We retry failures by default unless we're running a list of tests
# explicitly.
- if args.retry_limit is None and not args.positional_args:
+ if not args.retry_limit and not args.positional_args:
args.retry_limit = 3
try:
@@ -159,50 +70,110 @@ class RunTestsCommand(command_line.OptparseCommand):
'Re-run with --browser=list to see '
'available browser types.' % args.browser_type)
- json_results.ValidateArgs(parser, args)
+ @classmethod
+ def main(cls, args=None, stream=None): # pylint: disable=W0221
+ # We override the superclass so that we can hook in the 'stream' arg.
+ parser = cls.CreateParser()
+ cls.AddCommandLineArgs(parser)
+ options, positional_args = parser.parse_args(args)
+ options.positional_args = positional_args
+ cls.ProcessCommandLineArgs(parser, options)
+
+ obj = cls()
+ if stream is not None:
+ obj.stream = stream
+ return obj.Run(options)
def Run(self, args):
possible_browser = browser_finder.FindBrowser(args)
- test_suite, result = self.RunOneSuite(possible_browser, args)
-
- results = [result]
+ runner = typ.Runner()
+ if self.stream:
+ runner.host.stdout = self.stream
+
+ # Telemetry seems to overload the system if we run one test per core,
+ # so we scale things back a fair amount. Many of the telemetry tests
+ # are long-running, so there's a limit to how much parallelism we
+ # can effectively use for now anyway.
+ #
+ # It should be possible to handle multiple devices if we adjust
+ # the browser_finder code properly, but for now we only handle the one
+ # on Android and ChromeOS.
+ if possible_browser.platform.GetOSName() in ('android', 'chromeos'):
+ runner.args.jobs = 1
+ else:
+ runner.args.jobs = max(int(args.jobs) // 4, 1)
+
+ runner.args.metadata = args.metadata
+ runner.args.passthrough = args.passthrough
+ runner.args.retry_limit = args.retry_limit
+ runner.args.test_results_server = args.test_results_server
+ runner.args.test_type = args.test_type
+ runner.args.timing = args.timing
+ runner.args.top_level_dir = args.top_level_dir
+ runner.args.verbose = args.verbosity
+ runner.args.write_full_results_to = args.write_full_results_to
+ runner.args.write_trace_to = args.write_trace_to
+
+ runner.args.path.append(util.GetUnittestDataDir())
+
+ runner.classifier = GetClassifier(args, possible_browser)
+ runner.context = args
+ runner.setup_fn = _SetUpProcess
+ runner.teardown_fn = _TearDownProcess
+ runner.win_multiprocessing = typ.WinMultiprocessing.importable
+ try:
+ ret, _, _ = runner.run()
+ except KeyboardInterrupt:
+ print >> sys.stderr, "interrupted, exiting"
+ ret = 130
+ return ret
+
+
+def GetClassifier(args, possible_browser):
+ def ClassifyTest(test_set, test):
+ name = test.id()
+ if args.positional_args:
+ if _MatchesSelectedTest(name, args.positional_args,
+ args.exact_test_filter):
+ assert hasattr(test, '_testMethodName')
+ method = getattr(test, test._testMethodName) # pylint: disable=W0212
+ if decorators.ShouldBeIsolated(method, possible_browser):
+ test_set.isolated_tests.append(typ.TestInput(name))
+ else:
+ test_set.parallel_tests.append(typ.TestInput(name))
+ else:
+ assert hasattr(test, '_testMethodName')
+ method = getattr(test, test._testMethodName) # pylint: disable=W0212
+ should_skip, reason = decorators.ShouldSkip(method, possible_browser)
+ if should_skip and not args.run_disabled_tests:
+ test_set.tests_to_skip.append(typ.TestInput(name, msg=reason))
+ elif decorators.ShouldBeIsolated(method, possible_browser):
+ test_set.isolated_tests.append(typ.TestInput(name))
+ else:
+ test_set.parallel_tests.append(typ.TestInput(name))
- failed_tests = json_results.FailedTestNames(test_suite, result)
- retry_limit = args.retry_limit
+ return ClassifyTest
- while retry_limit and failed_tests:
- args.positional_args = failed_tests
- args.exact_test_filter = True
- _, result = self.RunOneSuite(possible_browser, args)
- results.append(result)
+def _MatchesSelectedTest(name, selected_tests, selected_tests_are_exact):
+ if not selected_tests:
+ return False
+ if selected_tests_are_exact:
+ return any(name in selected_tests)
+ else:
+ return any(test in name for test in selected_tests)
- failed_tests = json_results.FailedTestNames(test_suite, result)
- retry_limit -= 1
- full_results = json_results.FullResults(args, test_suite, results)
- json_results.WriteFullResultsIfNecessary(args, full_results)
+def _SetUpProcess(child, context): # pylint: disable=W0613
+ args = context
+ options_for_unittests.Push(args)
- err_occurred, err_str = json_results.UploadFullResultsIfNecessary(
- args, full_results)
- if err_occurred:
- for line in err_str.splitlines():
- logging.error(line)
- return 1
- return json_results.ExitCodeFromFullResults(full_results)
+def _TearDownProcess(child, context): # pylint: disable=W0613
+ browser_test_case.teardown_browser()
+ options_for_unittests.Pop()
- def RunOneSuite(self, possible_browser, args):
- test_suite = DiscoverTests(config.test_dirs, config.top_level_dir,
- possible_browser, args.positional_args,
- args.exact_test_filter, args.run_disabled_tests)
- runner = progress_reporter.TestRunner()
- result = runner.run(test_suite, config.progress_reporters,
- args.repeat_count, args)
- return test_suite, result
- @classmethod
- @RestoreLoggingLevel
- def main(cls, args=None):
- return super(RunTestsCommand, cls).main(args)
+if __name__ == '__main__':
+ RunTestsCommand.main()
« no previous file with comments | « tools/telemetry/telemetry/unittest/run_chromeos_tests.py ('k') | tools/telemetry/telemetry/unittest/run_tests_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698