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

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

Issue 700703003: Revert of 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: 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 1a827a9207155ff2f2a9476840ae102401e4be3c..de825d27986eebf83bdbcc3e27918b1495404b9c 100644
--- a/tools/telemetry/telemetry/unittest/run_tests.py
+++ b/tools/telemetry/telemetry/unittest/run_tests.py
@@ -1,29 +1,120 @@
# 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 sys
+
+import logging
+import unittest
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 util
-from telemetry.unittest import options_for_unittests
-from telemetry.unittest import browser_test_case
-
-util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'third_party', 'typ')
-
-import typ
+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
+
+
+config = None
class RunTestsCommand(command_line.OptparseCommand):
"""Run unit tests"""
usage = '[test_name ...] [<options>]'
-
- def __init__(self):
- super(RunTestsCommand, self).__init__()
- self.stream = sys.stdout
@classmethod
def CreateParser(cls):
@@ -40,24 +131,22 @@
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).')
-
- 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)
+ json_results.AddOptions(parser)
@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 not args.retry_limit and not args.positional_args:
+ if args.retry_limit is None and not args.positional_args:
args.retry_limit = 3
try:
@@ -70,110 +159,50 @@
'Re-run with --browser=list to see '
'available browser types.' % args.browser_type)
- @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)
+ json_results.ValidateArgs(parser, args)
def Run(self, args):
possible_browser = browser_finder.FindBrowser(args)
- 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))
-
- return ClassifyTest
-
-
-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)
-
-
-def _SetUpProcess(child, context): # pylint: disable=W0613
- args = context
- options_for_unittests.Push(args)
-
-
-def _TearDownProcess(child, context): # pylint: disable=W0613
- browser_test_case.teardown_browser()
- options_for_unittests.Pop()
-
-
-if __name__ == '__main__':
- RunTestsCommand.main()
+ test_suite, result = self.RunOneSuite(possible_browser, args)
+
+ results = [result]
+
+ failed_tests = json_results.FailedTestNames(test_suite, result)
+ retry_limit = args.retry_limit
+
+ 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)
+
+ 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)
+
+ 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 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)
« 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