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
14 def Main(base_dir, page_set_filenames):
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(base_dir, page_set_filenames))
23 class PageTestRunner(object):
31 return page_test_module.PageTest
34 def test_class_name(self):
37 def Run(self, base_dir, page_set_filenames):
38 test, ps, expectations = self.ParseCommandLine(sys.argv, base_dir,
40 results = page_runner.Run(test, ps, expectations, self._options)
41 results.PrintSummary()
42 return min(255, len(results.failures + results.errors))
44 def FindTestConstructors(self, base_dir):
45 # Look for both Tests and PageTests, but Tests get priority, because
46 test_constructors = discover.DiscoverClasses(
47 base_dir, base_dir, self.test_class)
48 test_constructors.update(discover.DiscoverClasses(
49 base_dir, base_dir, test_module.Test, index_by_class_name=True))
50 return test_constructors
52 def FindTestName(self, test_constructors, args):
53 """Find the test name in an arbitrary argument list.
55 We can't use the optparse parser, because the test may add its own
56 command-line options. If the user passed in any of those, the
57 optparse parsing will fail.
63 for arg in [self.GetModernizedTestName(a) for a in args]:
64 if arg in test_constructors:
69 def GetModernizedTestName(self, arg):
70 """Sometimes tests change names but buildbots keep calling the old name.
72 If arg matches an old test name, return the new test name instead.
73 Otherwise, return the arg.
77 def GetPageSet(self, test, page_set_filenames):
78 ps = test.CreatePageSet(self._args, self._options)
82 if len(self._args) < 2:
83 page_set_list = ',\n'.join(
84 sorted([os.path.relpath(f) for f in page_set_filenames]))
86 'No page set, file, or URL specified.\n'
87 'Available page sets:\n'
90 page_set_arg = self._args[1]
92 # We've been given a URL. Create a page set with just that URL.
93 if (page_set_arg.startswith('http://') or
94 page_set_arg.startswith('https://')):
95 self._options.allow_live_sites = True
96 return page_set.PageSet.FromDict({
97 'pages': [{'url': page_set_arg}]
98 }, os.path.dirname(__file__))
100 # We've been given a page set JSON. Load it.
101 if page_set_arg.endswith('.json'):
102 return page_set.PageSet.FromFile(page_set_arg)
104 # We've been given a file or directory. Create a page set containing it.
105 if os.path.exists(page_set_arg):
106 page_set_dict = {'pages': []}
108 def _AddFile(file_path):
109 page_set_dict['pages'].append({'url': 'file://' + file_path})
111 def _AddDir(dir_path):
112 for path in os.listdir(dir_path):
113 path = os.path.join(dir_path, path)
117 if os.path.isdir(path):
122 _AddPath(page_set_arg)
123 return page_set.PageSet.FromDict(page_set_dict, os.getcwd() + os.sep)
125 raise Exception('Did not understand "%s". Pass a page set, file or URL.' %
128 def ParseCommandLine(self, args, base_dir, page_set_filenames):
129 self._options = browser_options.BrowserFinderOptions()
130 self._parser = self._options.CreateParser(
131 '%%prog [options] %s page_set' % self.test_class_name)
133 test_constructors = self.FindTestConstructors(base_dir)
134 test_name = self.FindTestName(test_constructors, args)
137 test = test_constructors[test_name]()
138 if isinstance(test, test_module.Test):
139 page_test = test.test()
142 page_test.AddCommandLineOptions(self._parser)
143 page_runner.AddCommandLineOptions(self._parser)
145 _, self._args = self._parser.parse_args()
147 if len(self._args) < 1:
148 error_message = 'No %s specified.\nAvailable %ss:\n' % (
149 self.test_class_name, self.test_class_name)
150 test_list_string = ',\n'.join(sorted(test_constructors.keys()))
151 self.PrintParseError(error_message + test_list_string)
154 error_message = 'No %s named %s.\nAvailable %ss:\n' % (
155 self.test_class_name, self._args[0], self.test_class_name)
156 test_list_string = ',\n'.join(sorted(test_constructors.keys()))
157 self.PrintParseError(error_message + test_list_string)
159 if isinstance(test, test_module.Test):
160 ps = test.CreatePageSet(self._options)
161 expectations = test.CreateExpectations(ps)
163 ps = self.GetPageSet(test, page_set_filenames)
164 expectations = test.CreateExpectations(ps)
166 if len(self._args) > 2:
167 self.PrintParseError('Too many arguments.')
169 return page_test, ps, expectations
171 def PrintParseError(self, message):
172 self._parser.error(message)