Commit b55d82b9 authored by chrishenry@google.com's avatar chrishenry@google.com

Merge PageMeasurement to PageTest, move MeasurementFailure to

page_test.py.

Fixed all files that refer to MeasurementFailure in this patch. Rest of
subclasses of PageMeasurement will be fixed in a follow up patch.

BUG=383635

Review URL: https://codereview.chromium.org/434443003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@287703 0039d316-1c4b-4281-b951-d872f2087c98
parent 47a6449e
...@@ -9,10 +9,10 @@ import urlparse ...@@ -9,10 +9,10 @@ import urlparse
from integration_tests import chrome_proxy_metrics as metrics from integration_tests import chrome_proxy_metrics as metrics
from metrics import loading from metrics import loading
from telemetry.core import util from telemetry.core import util
from telemetry.page import page_measurement from telemetry.page import page_test
class ChromeProxyLatency(page_measurement.PageMeasurement): class ChromeProxyLatency(page_test.PageTest):
"""Chrome proxy latency measurement.""" """Chrome proxy latency measurement."""
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
...@@ -27,7 +27,7 @@ class ChromeProxyLatency(page_measurement.PageMeasurement): ...@@ -27,7 +27,7 @@ class ChromeProxyLatency(page_measurement.PageMeasurement):
loading.LoadingMetric().AddResults(tab, results) loading.LoadingMetric().AddResults(tab, results)
class ChromeProxyDataSaving(page_measurement.PageMeasurement): class ChromeProxyDataSaving(page_test.PageTest):
"""Chrome proxy data daving measurement.""" """Chrome proxy data daving measurement."""
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(ChromeProxyDataSaving, self).__init__(*args, **kwargs) super(ChromeProxyDataSaving, self).__init__(*args, **kwargs)
...@@ -44,7 +44,7 @@ class ChromeProxyDataSaving(page_measurement.PageMeasurement): ...@@ -44,7 +44,7 @@ class ChromeProxyDataSaving(page_measurement.PageMeasurement):
self._metrics.AddResultsForDataSaving(tab, results) self._metrics.AddResultsForDataSaving(tab, results)
class ChromeProxyValidation(page_measurement.PageMeasurement): class ChromeProxyValidation(page_test.PageTest):
"""Base class for all chrome proxy correctness measurements.""" """Base class for all chrome proxy correctness measurements."""
def __init__(self, restart_after_each_page=False): def __init__(self, restart_after_each_page=False):
...@@ -245,7 +245,7 @@ class ChromeProxySmoke(ChromeProxyValidation): ...@@ -245,7 +245,7 @@ class ChromeProxySmoke(ChromeProxyValidation):
'safebrowsing': [self._metrics.AddResultsForSafebrowsing], 'safebrowsing': [self._metrics.AddResultsForSafebrowsing],
} }
if not self._page.name in page_to_metrics: if not self._page.name in page_to_metrics:
raise page_measurement.MeasurementFailure( raise page_test.MeasurementFailure(
'Invalid page name (%s) in smoke. Page name must be one of:\n%s' % ( 'Invalid page name (%s) in smoke. Page name must be one of:\n%s' % (
self._page.name, page_to_metrics.keys())) self._page.name, page_to_metrics.keys()))
for add_result in page_to_metrics[self._page.name]: for add_result in page_to_metrics[self._page.name]:
......
...@@ -7,11 +7,11 @@ import logging ...@@ -7,11 +7,11 @@ import logging
import os import os
from integration_tests import network_metrics from integration_tests import network_metrics
from telemetry.page import page_measurement from telemetry.page import page_test
from telemetry.value import scalar from telemetry.value import scalar
class ChromeProxyMetricException(page_measurement.MeasurementFailure): class ChromeProxyMetricException(page_test.MeasurementFailure):
pass pass
......
...@@ -10,14 +10,14 @@ import logging ...@@ -10,14 +10,14 @@ import logging
import zlib import zlib
from metrics import Metric from metrics import Metric
from telemetry.page import page_measurement from telemetry.page import page_test
# All network metrics are Chrome only for now. # All network metrics are Chrome only for now.
from telemetry.core.backends.chrome import inspector_network from telemetry.core.backends.chrome import inspector_network
from telemetry.timeline import recording_options from telemetry.timeline import recording_options
from telemetry.value import scalar from telemetry.value import scalar
class NetworkMetricException(page_measurement.MeasurementFailure): class NetworkMetricException(page_test.MeasurementFailure):
pass pass
......
...@@ -6,12 +6,11 @@ import sys ...@@ -6,12 +6,11 @@ import sys
import time import time
from telemetry.core.util import TimeoutException from telemetry.core.util import TimeoutException
from telemetry.page import page_measurement
from telemetry.page import page_test from telemetry.page import page_test
from telemetry.value import scalar from telemetry.value import scalar
class RasterizeAndRecordMicro(page_measurement.PageMeasurement): class RasterizeAndRecordMicro(page_test.PageTest):
def __init__(self): def __init__(self):
super(RasterizeAndRecordMicro, self).__init__('') super(RasterizeAndRecordMicro, self).__init__('')
self._chrome_branch_number = None self._chrome_branch_number = None
...@@ -83,7 +82,7 @@ class RasterizeAndRecordMicro(page_measurement.PageMeasurement): ...@@ -83,7 +82,7 @@ class RasterizeAndRecordMicro(page_measurement.PageMeasurement):
benchmark_id = tab.EvaluateJavaScript('window.benchmark_results.id') benchmark_id = tab.EvaluateJavaScript('window.benchmark_results.id')
if (not benchmark_id): if (not benchmark_id):
raise page_measurement.MeasurementFailure( raise page_test.MeasurementFailure(
'Failed to schedule rasterize_and_record_micro') 'Failed to schedule rasterize_and_record_micro')
tab.WaitForJavaScriptExpression( tab.WaitForJavaScriptExpression(
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
# found in the LICENSE file. # found in the LICENSE file.
from measurements import smoothness_controller from measurements import smoothness_controller
from telemetry.page import page_measurement from telemetry.page import page_test
class Repaint(page_measurement.PageMeasurement): class Repaint(page_test.PageTest):
def __init__(self): def __init__(self):
super(Repaint, self).__init__('RunRepaint', False) super(Repaint, self).__init__('RunRepaint', False)
self._smoothness_controller = None self._smoothness_controller = None
...@@ -62,7 +62,7 @@ class Repaint(page_measurement.PageMeasurement): ...@@ -62,7 +62,7 @@ class Repaint(page_measurement.PageMeasurement):
self._micro_benchmark_id = tab.EvaluateJavaScript( self._micro_benchmark_id = tab.EvaluateJavaScript(
'window.benchmark_results.id') 'window.benchmark_results.id')
if (not self._micro_benchmark_id): if (not self._micro_benchmark_id):
raise page_measurement.MeasurementFailure( raise page_test.MeasurementFailure(
'Failed to schedule invalidation_benchmark.') 'Failed to schedule invalidation_benchmark.')
def DidRunActions(self, page, tab): def DidRunActions(self, page, tab):
......
...@@ -4,14 +4,14 @@ ...@@ -4,14 +4,14 @@
import glob import glob
import os import os
from telemetry.page import page_measurement from telemetry.page import page_test
from telemetry.value import scalar from telemetry.value import scalar
_JS = 'chrome.gpuBenchmarking.printToSkPicture("{0}");' _JS = 'chrome.gpuBenchmarking.printToSkPicture("{0}");'
class SkpicturePrinter(page_measurement.PageMeasurement): class SkpicturePrinter(page_test.PageTest):
@classmethod @classmethod
def AddCommandLineArgs(cls, parser): def AddCommandLineArgs(cls, parser):
parser.add_option('-s', '--skp-outdir', parser.add_option('-s', '--skp-outdir',
...@@ -30,7 +30,7 @@ class SkpicturePrinter(page_measurement.PageMeasurement): ...@@ -30,7 +30,7 @@ class SkpicturePrinter(page_measurement.PageMeasurement):
def MeasurePage(self, page, tab, results): def MeasurePage(self, page, tab, results):
if tab.browser.platform.GetOSName() in ['android', 'chromeos']: if tab.browser.platform.GetOSName() in ['android', 'chromeos']:
raise page_measurement.MeasurementFailure( raise page_test.MeasurementFailure(
'SkPicture printing not supported on this platform') 'SkPicture printing not supported on this platform')
# Replace win32 path separator char '\' with '\\'. # Replace win32 path separator char '\' with '\\'.
......
...@@ -5,7 +5,7 @@ import sys ...@@ -5,7 +5,7 @@ import sys
from measurements import smooth_gesture_util from measurements import smooth_gesture_util
from telemetry.timeline.model import TimelineModel from telemetry.timeline.model import TimelineModel
from telemetry.page import page_measurement from telemetry.page import page_test
from telemetry.page.actions import action_runner from telemetry.page.actions import action_runner
from telemetry.value import list_of_scalar_values from telemetry.value import list_of_scalar_values
from telemetry.value import scalar from telemetry.value import scalar
...@@ -22,7 +22,7 @@ DESCRIPTIONS = { ...@@ -22,7 +22,7 @@ DESCRIPTIONS = {
} }
class MissingDisplayFrameRateError(page_measurement.MeasurementFailure): class MissingDisplayFrameRateError(page_test.MeasurementFailure):
def __init__(self, name): def __init__(self, name):
super(MissingDisplayFrameRateError, self).__init__( super(MissingDisplayFrameRateError, self).__init__(
'Missing display frame rate metrics: ' + name) 'Missing display frame rate metrics: ' + name)
......
...@@ -5,44 +5,8 @@ ...@@ -5,44 +5,8 @@
from telemetry.page import page_test from telemetry.page import page_test
class MeasurementFailure(page_test.Failure):
"""Exception that can be thrown from MeasurePage to indicate an undesired but
designed-for problem."""
class PageMeasurement(page_test.PageTest): class PageMeasurement(page_test.PageTest):
"""Glue code for running a measurement across a set of pages. """DEPRECATED: Please extend page_test.PageTest directly."""
To use this, subclass from the measurement and override MeasurePage. For
example:
class BodyChildElementMeasurement(PageMeasurement):
def MeasurePage(self, page, tab, results):
body_child_count = tab.EvaluateJavaScript(
'document.body.children.length')
results.AddValue(scalar.ScalarValue(
page, 'body_children', 'count', body_child_count))
if __name__ == '__main__':
page_measurement.Main(BodyChildElementMeasurement())
To add test-specific options:
class BodyChildElementMeasurement(PageMeasurement):
def AddCommandLineArgs(parser):
parser.add_option('--element', action='store', default='body')
def MeasurePage(self, page, tab, results):
body_child_count = tab.EvaluateJavaScript(
'document.querySelector('%s').children.length')
results.AddValue(scalar.ScalarValue(
page, 'children', 'count', child_count))
is_action_name_to_run_optional determines what to do if action_name_to_run is
not empty but the page doesn't have that action. The page will run (without
any action) if is_action_name_to_run_optional is True, otherwise the page will
fail.
"""
def __init__(self, def __init__(self,
action_name_to_run='', action_name_to_run='',
needs_browser_restart_after_each_page=False, needs_browser_restart_after_each_page=False,
...@@ -55,30 +19,3 @@ class PageMeasurement(page_test.PageTest): ...@@ -55,30 +19,3 @@ class PageMeasurement(page_test.PageTest):
discard_first_result, discard_first_result,
clear_cache_before_each_run, clear_cache_before_each_run,
is_action_name_to_run_optional=is_action_name_to_run_optional) is_action_name_to_run_optional=is_action_name_to_run_optional)
def ValidatePage(self, page, tab, results):
self.MeasurePage(page, tab, results)
def MeasurePage(self, page, tab, results):
"""Override to actually measure the page's performance.
page is a page_set.Page
tab is an instance of telemetry.core.Tab
Should call results.AddValue(...) for each result, or raise an
exception on failure. The name and units of each Add() call must be
the same across all iterations. The name 'url' must not be used.
Prefer field names that are in accordance with python variable style. E.g.
field_name.
Put together:
def MeasurePage(self, page, tab, results):
res = tab.EvaluateJavaScript('2+2')
if res != 4:
raise Exception('Oh, wow.')
results.AddValue(scalar.ScalarValue(
page, 'two_plus_two', 'count', res))
"""
raise NotImplementedError()
...@@ -9,53 +9,53 @@ from telemetry import benchmark ...@@ -9,53 +9,53 @@ from telemetry import benchmark
from telemetry.core import exceptions from telemetry.core import exceptions
from telemetry.core import wpr_modes from telemetry.core import wpr_modes
from telemetry.page import page as page_module from telemetry.page import page as page_module
from telemetry.page import page_measurement
from telemetry.page import page_measurement_unittest_base from telemetry.page import page_measurement_unittest_base
from telemetry.page import page_set from telemetry.page import page_set
from telemetry.page import page_set_archive_info from telemetry.page import page_set_archive_info
from telemetry.page import page_test
from telemetry.unittest import options_for_unittests from telemetry.unittest import options_for_unittests
from telemetry.value import scalar from telemetry.value import scalar
class MeasurementThatFails(page_measurement.PageMeasurement): class MeasurementThatFails(page_test.PageTest):
def MeasurePage(self, page, tab, results): def MeasurePage(self, page, tab, results):
raise exceptions.IntentionalException raise exceptions.IntentionalException
class MeasurementThatHasDefaults(page_measurement.PageMeasurement): class MeasurementThatHasDefaults(page_test.PageTest):
def AddCommandLineArgs(self, parser): def AddCommandLineArgs(self, parser):
parser.add_option('-x', dest='x', default=3) parser.add_option('-x', dest='x', default=3)
def MeasurePage(self, page, tab, results): def MeasurePage(self, page, tab, results):
if not hasattr(self.options, 'x'): if not hasattr(self.options, 'x'):
raise page_measurement.MeasurementFailure('Default option was not set.') raise page_test.MeasurementFailure('Default option was not set.')
if self.options.x != 3: if self.options.x != 3:
raise page_measurement.MeasurementFailure( raise page_test.MeasurementFailure(
'Expected x == 3, got x == ' + self.options.x) 'Expected x == 3, got x == ' + self.options.x)
results.AddValue(scalar.ScalarValue(page, 'x', 'ms', 7)) results.AddValue(scalar.ScalarValue(page, 'x', 'ms', 7))
class MeasurementForBlank(page_measurement.PageMeasurement): class MeasurementForBlank(page_test.PageTest):
def MeasurePage(self, page, tab, results): def MeasurePage(self, page, tab, results):
contents = tab.EvaluateJavaScript('document.body.textContent') contents = tab.EvaluateJavaScript('document.body.textContent')
if contents.strip() != 'Hello world': if contents.strip() != 'Hello world':
raise page_measurement.MeasurementFailure( raise page_test.MeasurementFailure(
'Page contents were: ' + contents) 'Page contents were: ' + contents)
class MeasurementForReplay(page_measurement.PageMeasurement): class MeasurementForReplay(page_test.PageTest):
def MeasurePage(self, page, tab, results): def MeasurePage(self, page, tab, results):
# Web Page Replay returns '404 Not found' if a page is not in the archive. # Web Page Replay returns '404 Not found' if a page is not in the archive.
contents = tab.EvaluateJavaScript('document.body.textContent') contents = tab.EvaluateJavaScript('document.body.textContent')
if '404 Not Found' in contents.strip(): if '404 Not Found' in contents.strip():
raise page_measurement.MeasurementFailure('Page not in archive.') raise page_test.MeasurementFailure('Page not in archive.')
class MeasurementQueryParams(page_measurement.PageMeasurement): class MeasurementQueryParams(page_test.PageTest):
def MeasurePage(self, page, tab, results): def MeasurePage(self, page, tab, results):
query = tab.EvaluateJavaScript('window.location.search') query = tab.EvaluateJavaScript('window.location.search')
expected = '?foo=1' expected = '?foo=1'
if query.strip() != expected: if query.strip() != expected:
raise page_measurement.MeasurementFailure( raise page_test.MeasurementFailure(
'query was %s, not %s.' % (query, expected)) 'query was %s, not %s.' % (query, expected))
class MeasurementWithAction(page_measurement.PageMeasurement): class MeasurementWithAction(page_test.PageTest):
def __init__(self): def __init__(self):
super(MeasurementWithAction, self).__init__('RunTestAction') super(MeasurementWithAction, self).__init__('RunTestAction')
......
...@@ -19,8 +19,56 @@ class TestNotSupportedOnPlatformFailure(Failure): ...@@ -19,8 +19,56 @@ class TestNotSupportedOnPlatformFailure(Failure):
browser version.""" browser version."""
class MeasurementFailure(Failure):
"""Exception that can be thrown from MeasurePage to indicate an undesired but
designed-for problem."""
class PageTest(command_line.Command): class PageTest(command_line.Command):
"""A class styled on unittest.TestCase for creating page-specific tests.""" """A class styled on unittest.TestCase for creating page-specific tests.
This class also support running a measurement by default (but can be
overridden by overriding ValidatePage method).
To use this for measurement, subclass from the measurement and
override MeasurePage. For example:
class BodyChildElementMeasurement(PageTest):
def MeasurePage(self, page, tab, results):
body_child_count = tab.EvaluateJavaScript(
'document.body.children.length')
results.AddValue(scalar.ScalarValue(
page, 'body_children', 'count', body_child_count))
The class also provide hooks to add test-specific options. Here is
an example:
class BodyChildElementMeasurement(PageTest):
def AddCommandLineArgs(parser):
parser.add_option('--element', action='store', default='body')
def MeasurePage(self, page, tab, results):
body_child_count = tab.EvaluateJavaScript(
'document.querySelector('%s').children.length')
results.AddValue(scalar.ScalarValue(
page, 'children', 'count', child_count))
Args:
action_name_to_run: This is the method name in telemetry.page.Page
subclasses to run.
discard_first_run: Discard the first run of this page. This is
usually used with page_repeat and pageset_repeat options.
attempts: The number of attempts to run if we encountered
infrastructure problems (as opposed to test issues), such as
losing a browser.
max_failures: The number of page failures allowed before we stop
running other pages.
is_action_name_to_run_optional: Determines what to do if
action_name_to_run is not empty but the page doesn't have that
action. The page will run (without any action) if
is_action_name_to_run_optional is True, otherwise the page
will fail.
"""
options = {} options = {}
...@@ -218,8 +266,34 @@ class PageTest(command_line.Command): ...@@ -218,8 +266,34 @@ class PageTest(command_line.Command):
def ValidatePage(self, page, tab, results): def ValidatePage(self, page, tab, results):
"""Override to check the actual test assertions. """Override to check the actual test assertions.
This is where most your test logic should go.""" This is where most your test logic should go. By default it runs
raise NotImplementedError() self.MeasurePage.
"""
self.MeasurePage(page, tab, results)
def MeasurePage(self, page, tab, results):
"""Override to actually measure the page's performance.
Should call results.AddValue(...) for each result. Can raise an
exception of add a failure.FailureValue on failure.
Prefer metric value names that are in accordance with python
variable style. e.g., metric_name. The name 'url' must not be used.
Put together:
def MeasurePage(self, page, tab, results):
res = tab.EvaluateJavaScript('2+2')
if res != 4:
raise Exception('Oh, wow.')
results.AddValue(scalar.ScalarValue(
page, 'two_plus_two', 'count', res))
Args:
page: A telemetry.page.Page instance.
tab: A telemetry.core.Tab instance.
results: A telemetry.results.PageTestResults instance.
"""
def RunPage(self, page, tab, results): def RunPage(self, page, tab, results):
# Run actions. # Run actions.
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
import logging import logging
from operator import attrgetter from operator import attrgetter
from telemetry.page import page_measurement from telemetry.page import page_test
from telemetry.web_perf.metrics import rendering_frame from telemetry.web_perf.metrics import rendering_frame
# These are LatencyInfo component names indicating the various components # These are LatencyInfo component names indicating the various components
...@@ -19,7 +19,7 @@ BEGIN_COMP_NAME = 'INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT' ...@@ -19,7 +19,7 @@ BEGIN_COMP_NAME = 'INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT'
END_COMP_NAME = 'INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT' END_COMP_NAME = 'INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT'
class NotEnoughFramesError(page_measurement.MeasurementFailure): class NotEnoughFramesError(page_test.MeasurementFailure):
def __init__(self, frame_count): def __init__(self, frame_count):
super(NotEnoughFramesError, self).__init__( super(NotEnoughFramesError, self).__init__(
'Only %i frame timestamps were collected ' % frame_count + 'Only %i frame timestamps were collected ' % frame_count +
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment