Chromium Code Reviews| Index: tools/telemetry/telemetry/test_runner.py |
| diff --git a/tools/telemetry/telemetry/test_runner.py b/tools/telemetry/telemetry/test_runner.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..57bf2c982acb42f700ec597d363b77ec55f2ab72 |
| --- /dev/null |
| +++ b/tools/telemetry/telemetry/test_runner.py |
| @@ -0,0 +1,147 @@ |
| +# Copyright (c) 2013 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. |
| +"""Parses the command line, discovers the appropriate tests, and runs them. |
| + |
| +Handles test configuration, but all the logic for |
| +actually running the test is in PageRunner.""" |
|
tonyg
2013/06/19 16:40:15
Recommend line breaks around the docstring
dtu
2013/06/19 21:22:58
Done.
|
| +import copy |
| +import inspect |
| +import optparse |
| +import os |
| +import sys |
| + |
| +from telemetry import test |
| +from telemetry.core import browser_options |
| +from telemetry.core import discover |
| + |
| + |
| +class Command(object): |
| + usage = '' |
| + |
| + @property |
| + def name(self): |
| + return self.__class__.__name__.lower() |
| + |
| + @property |
| + def description(self): |
| + return self.__doc__ |
| + |
| + def CreateParser(self): |
| + return optparse.OptionParser('%%prog %s %s' % (self.name, self.usage)) |
| + |
| + def ValidateCommandLine(self, parser, args, options): |
| + pass |
| + |
| + def Run(self, args, options): |
| + raise NotImplementedError() |
| + |
| + |
| +class Help(Command): |
| + """Display help information""" |
| + |
| + def Run(self, args, options): |
| + print >> sys.stderr, ('usage: %s <command> [<args>]' % _GetScriptName()) |
| + print >> sys.stderr, 'Available commands are:' |
| + for command in COMMANDS: |
| + print >> sys.stderr, ' %-10s %s' % (command.name, command.description) |
| + return 0 |
| + |
| + |
| +class List(Command): |
| + """Lists the available tests""" |
| + |
|
nduca
2013/06/19 05:46:53
lets get a --json version of this in here quick so
dtu
2013/06/19 21:22:58
Done.
|
| + def Run(self, args, options): |
| + print >> sys.stderr, 'Available tests are:' |
| + for test_name, test_class in sorted(_GetTests().items()): |
| + print >> sys.stderr, ' %-20s %s' % (test_name, |
| + test_class.__doc__.splitlines()[0]) |
| + return 0 |
| + |
| + |
| +class Run(Command): |
| + """Run one or more tests""" |
| + |
| + usage = '[test_names ...] [<args>]' |
| + |
| + def CreateParser(self): |
| + options = browser_options.BrowserOptions() |
| + parser = options.CreateParser('%%prog %s %s' % (self.name, self.usage)) |
| + return parser |
| + |
| + def ValidateCommandLine(self, parser, test_names, options): |
| + for test_name in test_names: |
| + if test_name not in _GetTests(): |
| + parser.error('No test named "%s"' % test_name) |
| + |
| + def Run(self, test_names, options): |
|
nduca
2013/06/19 05:46:53
bit awk that you have test_names here instead of a
dtu
2013/06/19 06:07:10
Ugh, okay. It was like this because positional arg
dtu
2013/06/19 21:22:58
Done.
|
| + if not test_names: |
|
nduca
2013/06/19 05:46:53
maybe we should parser.error in this case. i think
dtu
2013/06/19 21:22:58
Done.
|
| + test_names = [test_name for test_name, test_class |
| + in _GetTests().iteritems() if test_class.enabled] |
| + |
| + total_failures = 0 |
| + for test_name in test_names: |
| + test_failures = _GetTests()[test_name]().Run(copy.copy(options)) |
| + total_failures += test_failures |
| + |
| + return min(255, total_failures) |
| + |
| + |
| +COMMANDS = [cls() for _, cls in inspect.getmembers(sys.modules[__name__]) |
| + if inspect.isclass(cls) |
| + and cls is not Command and issubclass(cls, Command)] |
| + |
| + |
| +def _GetScriptName(): |
| + return os.path.basename(sys.argv[0]) |
| + |
| + |
| +def _GetBaseDir(): |
| + main_module = sys.modules['__main__'] |
| + if hasattr(main_module, '__file__'): |
| + return os.path.dirname(main_module.__file__) |
| + else: |
| + return os.getcwd() |
| + |
| + |
| +def _GetTests(): |
| + # Lazy load and cache results. |
| + if not hasattr(_GetTests, 'tests'): |
| + base_dir = _GetBaseDir() |
| + _GetTests.tests = discover.DiscoverClasses(base_dir, base_dir, test.Test, |
| + index_by_class_name=True) |
| + return _GetTests.tests |
| + |
| + |
| +def Main(): |
| + # Get the command name from the command line. |
| + if len(sys.argv) > 1 and sys.argv[1] == '--help': |
| + sys.argv[1] = 'help' |
| + |
| + command_name = 'run' |
| + for arg in sys.argv[1:]: |
| + if not arg.startswith('-'): |
| + command_name = arg |
| + break |
| + |
| + # Validate and interpret the command name. |
| + commands = [command for command in COMMANDS |
| + if command.name.startswith(command_name)] |
| + if len(commands) > 1: |
| + print >> sys.stderr, ('"%s" is not a %s command. Did you mean one of these?' |
| + % (command_name, _GetScriptName())) |
| + for command in commands: |
| + print >> sys.stderr, ' %-10s %s' % (command.name, command.description) |
| + return 1 |
| + if commands: |
| + command = commands[0] |
| + else: |
| + command = Run() |
| + |
| + # Parse and run the command. |
| + parser = command.CreateParser() |
| + options, args = parser.parse_args() |
| + if commands: |
| + args = args[1:] |
| + command.ValidateCommandLine(parser, args, options) |
| + return command.Run(args, options) |