1# Copyright 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. 4 5from telemetry.page import page_test 6 7 8class MeasurementFailure(page_test.Failure): 9 """Exception that can be thrown from MeasurePage to indicate an undesired but 10 designed-for problem.""" 11 12 13class PageMeasurement(page_test.PageTest): 14 """Glue code for running a measurement across a set of pages. 15 16 To use this, subclass from the measurement and override MeasurePage. For 17 example: 18 19 class BodyChildElementMeasurement(PageMeasurement): 20 def MeasurePage(self, page, tab, results): 21 body_child_count = tab.EvaluateJavaScript( 22 'document.body.children.length') 23 results.Add('body_children', 'count', body_child_count) 24 25 if __name__ == '__main__': 26 page_measurement.Main(BodyChildElementMeasurement()) 27 28 To add test-specific options: 29 30 class BodyChildElementMeasurement(PageMeasurement): 31 def AddCommandLineArgs(parser): 32 parser.add_option('--element', action='store', default='body') 33 34 def MeasurePage(self, page, tab, results): 35 body_child_count = tab.EvaluateJavaScript( 36 'document.querySelector('%s').children.length') 37 results.Add('children', 'count', child_count) 38 39 is_action_name_to_run_optional determines what to do if action_name_to_run is 40 not empty but the page doesn't have that action. The page will run (without 41 any action) if is_action_name_to_run_optional is True, otherwise the page will 42 fail. 43 """ 44 def __init__(self, 45 action_name_to_run='', 46 needs_browser_restart_after_each_page=False, 47 discard_first_result=False, 48 clear_cache_before_each_run=False, 49 is_action_name_to_run_optional=False): 50 super(PageMeasurement, self).__init__( 51 action_name_to_run, 52 needs_browser_restart_after_each_page, 53 discard_first_result, 54 clear_cache_before_each_run, 55 is_action_name_to_run_optional=is_action_name_to_run_optional) 56 57 def ValidatePage(self, page, tab, results): 58 results.WillMeasurePage(page) 59 try: 60 self.MeasurePage(page, tab, results) 61 finally: 62 results.DidMeasurePage() 63 64 @property 65 def results_are_the_same_on_every_page(self): 66 """By default, measurements are assumed to output the same values for every 67 page. This allows incremental output, for example in CSV. If, however, the 68 measurement discovers what values it can report as it goes, and those values 69 may vary from page to page, you need to override this function and return 70 False. Output will not appear in this mode until the entire pageset has 71 run.""" 72 return True 73 74 def MeasurePage(self, page, tab, results): 75 """Override to actually measure the page's performance. 76 77 page is a page_set.Page 78 tab is an instance of telemetry.core.Tab 79 80 Should call results.Add(name, units, value) for each result, or raise an 81 exception on failure. The name and units of each Add() call must be 82 the same across all iterations. The name 'url' must not be used. 83 84 Prefer field names that are in accordance with python variable style. E.g. 85 field_name. 86 87 Put together: 88 89 def MeasurePage(self, page, tab, results): 90 res = tab.EvaluateJavaScript('2+2') 91 if res != 4: 92 raise Exception('Oh, wow.') 93 results.Add('two_plus_two', 'count', res) 94 """ 95 raise NotImplementedError() 96