1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
7 from telemetry import test as test_module
8 from telemetry.core import browser_options
9 from telemetry.core import discover
10 from telemetry.page import page_test as page_test_module
11 from telemetry.page import page_runner
12 from telemetry.page import page_set
15 """Turns a PageTest into a command-line program.
18 base_dir: Path to directory containing tests and ProfileCreators.
20 runner = PageTestRunner()
21 sys.exit(runner.Run(env))
23 class PageTestRunner(object):
31 return page_test_module.PageTest
34 def test_class_name(self):
38 test, ps, expectations = self.ParseCommandLine(sys.argv, env)
39 results = page_runner.Run(test, ps, expectations, self._options)
40 results.PrintSummary()
41 return min(255, len(results.failures + results.errors))
43 def FindTestConstructors(self, base_dirs):
44 # Look for both Tests and PageTests, but Tests get priority, because
45 test_constructors = {}
46 for base_dir in base_dirs:
47 test_constructors.update(discover.DiscoverClasses(
48 base_dir, base_dir, self.test_class))
49 for base_dir in base_dirs:
50 test_constructors.update(discover.DiscoverClasses(
51 base_dir, base_dir, test_module.Test, index_by_class_name=True))
52 return test_constructors
54 def FindTestName(self, test_constructors, args):
55 """Find the test name in an arbitrary argument list.
57 We can't use the optparse parser, because the test may add its own
58 command-line options. If the user passed in any of those, the
59 optparse parsing will fail.
66 if arg in test_constructors:
71 def GetPageSet(self, env):
72 if len(self._args) < 2:
73 page_set_filenames = []
74 for perf_path in env.base_paths:
75 # Check if page_sets subfolder is present, and get all page_sets
77 page_set_dir = os.path.join(perf_path, "page_sets")
78 if not os.path.exists(page_set_dir):
80 page_set_filenames += discover.GetAllPageSetFilenames(page_set_dir)
81 page_set_list = ',\n'.join(
82 sorted([os.path.relpath(f) for f in page_set_filenames]))
84 'No page set, file, or URL specified.\n'
85 'Available page sets:\n'
88 page_set_arg = self._args[1]
90 # We've been given a URL. Create a page set with just that URL.
91 if (page_set_arg.startswith('http://') or
92 page_set_arg.startswith('https://')):
93 self._options.allow_live_sites = True
94 return page_set.PageSet.FromDict({
95 'pages': [{'url': page_set_arg}]
96 }, os.path.dirname(__file__))
98 # We've been given a page set JSON or PYTHON. Load it.
99 if page_set_arg.endswith('.json') or page_set_arg.endswith('.py'):
100 return page_set.PageSet.FromFile(page_set_arg)
102 # We've been given a file or directory. Create a page set containing it.
103 if os.path.exists(page_set_arg):
104 page_set_dict = {'pages': []}
106 def _AddFile(file_path):
107 page_set_dict['pages'].append({'url': 'file://' + file_path})
109 def _AddDir(dir_path):
110 for path in os.listdir(dir_path):
111 path = os.path.join(dir_path, path)
115 if os.path.isdir(path):
120 _AddPath(page_set_arg)
121 return page_set.PageSet.FromDict(page_set_dict, os.getcwd() + os.sep)
123 raise Exception('Did not understand "%s". Pass a page set, file or URL.' %
126 def ParseCommandLine(self, args, env):
127 self._options = browser_options.BrowserFinderOptions()
128 self._parser = self._options.CreateParser(
129 '%%prog [options] %s page_set' % self.test_class_name)
131 test_constructors = self.FindTestConstructors(env.base_paths)
132 test_name = self.FindTestName(test_constructors, args)
135 test = test_constructors[test_name]()
136 if isinstance(test, test_module.Test):
137 page_test = test.test()
138 test.AddCommandLineArgs(self._parser)
141 page_test.AddCommandLineArgs(self._parser)
142 page_runner.AddCommandLineArgs(self._parser)
144 _, self._args = self._parser.parse_args()
146 if len(self._args) < 1:
147 error_message = 'No %s specified.\nAvailable %ss:\n' % (
148 self.test_class_name, self.test_class_name)
149 test_list_string = ',\n'.join(sorted(test_constructors.keys()))
150 self.PrintParseError(error_message + test_list_string)
153 error_message = 'No %s named %s.\nAvailable %ss:\n' % (
154 self.test_class_name, self._args[0], self.test_class_name)
155 test_list_string = ',\n'.join(sorted(test_constructors.keys()))
156 self.PrintParseError(error_message + test_list_string)
158 if isinstance(test, test_module.Test):
159 ps = test.CreatePageSet(self._options)
160 expectations = test.CreateExpectations(ps)
161 test.ProcessCommandLineArgs(self._parser, self._options)
163 ps = self.GetPageSet(env)
164 expectations = test.CreateExpectations(ps)
165 page_test.ProcessCommandLineArgs(self._parser, self._options)
166 page_runner.ProcessCommandLineArgs(self._parser, self._options)
168 if len(self._args) > 2:
169 self.PrintParseError('Too many arguments.')
172 return page_test, ps, expectations
174 def PrintParseError(self, message):
175 self._parser.error(message)