Commit 9b9a3628 authored by nednguyen's avatar nednguyen Committed by Commit bot

[Telemetry] Add __enter__ & __exit__ methods for action_runner.Interaction.

BUG=475090

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

Cr-Commit-Position: refs/heads/master@{#324315}
parent 647f1bac
# Copyright 2014 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.
import unittest
from telemetry.core import exceptions
from telemetry.core.platform import tracing_category_filter
from telemetry.core.platform import tracing_options
from telemetry.core import util
from telemetry import decorators
from telemetry.internal.actions import page_action
from telemetry.page import action_runner as action_runner_module
......@@ -12,6 +14,9 @@ from telemetry.timeline import model
from telemetry.unittest_util import tab_test_case
from telemetry.web_perf import timeline_interaction_record as tir_module
util.AddDirToPythonPath(util.GetTelemetryDir(), 'third_party', 'mock')
import mock
class ActionRunnerInteractionTest(tab_test_case.TabTestCase):
......@@ -33,9 +38,9 @@ class ActionRunnerInteractionTest(tab_test_case.TabTestCase):
options.enable_chrome_trace = True
self._browser.platform.tracing_controller.Start(
options, tracing_category_filter.CreateNoOverheadFilter())
interaction = action_runner.BeginInteraction('InteractionName',
**interaction_kwargs)
interaction.End()
with action_runner.CreateInteraction('InteractionName',
**interaction_kwargs):
pass
trace_data = self._browser.platform.tracing_controller.Stop()
records = self.GetInteractionRecords(trace_data)
......@@ -248,3 +253,34 @@ class ActionRunnerTest(tab_test_case.TabTestCase):
action_runner.SwipePage(direction='left', left_start_ratio=0.9)
self.assertTrue(action_runner.EvaluateJavaScript(
'document.body.scrollLeft') > 75)
class InteractionTest(unittest.TestCase):
def setUp(self):
self.mock_action_runner = mock.Mock(action_runner_module.ActionRunner)
def testIssuingInteractionRecordCommand(self):
with action_runner_module.Interaction(
self.mock_action_runner, label='ABC', flags=[]):
pass
expected_calls = [
mock.call.ExecuteJavaScript('console.time("Interaction.ABC");'),
mock.call.ExecuteJavaScript('console.timeEnd("Interaction.ABC");')]
self.assertEqual(expected_calls, self.mock_action_runner.mock_calls)
def testExceptionRaisedInWithInteraction(self):
class FooException(Exception):
pass
# Test that the Foo exception raised in the with block is propagated to the
# caller.
with self.assertRaises(FooException):
with action_runner_module.Interaction(
self.mock_action_runner, label='ABC', flags=[]):
raise FooException()
# Test that the end console.timeEnd(...) isn't called because exception was
# raised.
expected_calls = [
mock.call.ExecuteJavaScript('console.time("Interaction.ABC");')]
self.assertEqual(expected_calls, self.mock_action_runner.mock_calls)
......@@ -6,6 +6,7 @@ import logging
import time
import urlparse
from telemetry.core import exceptions
from telemetry.internal.actions.drag import DragAction
from telemetry.internal.actions.javascript_click import ClickElementAction
from telemetry.internal.actions.loop import LoopAction
......@@ -34,6 +35,7 @@ class ActionRunner(object):
action.WillRunAction(self._tab)
action.RunAction(self._tab)
# TODO(nednguyen): remove this API when crbug.com/475090 is fixed.
def BeginInteraction(self, label, repeatable=False):
"""Marks the beginning of an interaction record.
......@@ -58,6 +60,7 @@ class ActionRunner(object):
interaction.Begin()
return interaction
# TODO(nednguyen): remove this API when crbug.com/475090 is fixed.
def BeginGestureInteraction(self, label, repeatable=False):
"""Marks the beginning of a gesture-based interaction record.
......@@ -78,6 +81,67 @@ class ActionRunner(object):
"""
return self.BeginInteraction('Gesture_' + label, repeatable)
def CreateInteraction(self, label, repeatable=False):
""" Create an action.Interaction object that issues interaction record.
An interaction record is a labeled time period containing
interaction that developers care about. Each set of metrics
specified in flags will be calculated for this time period.
To mark the start of interaction record, call Begin() method on the returned
object. To mark the finish of interaction record, call End() method on
it. Or better yet, use the with statement to create an
interaction record that covers the actions in the with block.
e.g:
with action_runner.CreateInteraction('Animation-1'):
action_runner.TapElement(...)
action_runner.WaitForJavaScriptCondition(...)
Args:
label: A label for this particular interaction. This can be any
user-defined string, but must not contain '/'.
repeatable: Whether other interactions may use the same logical name
as this interaction. All interactions with the same logical name must
have the same flags.
Returns:
An instance of action_runner.Interaction
"""
flags = []
if repeatable:
flags.append(timeline_interaction_record.REPEATABLE)
return Interaction(self._tab, label, flags)
def CreateGestureInteraction(self, label, repeatable=False):
""" Create an action.Interaction object that issues gesture-based
interaction record.
This is similar to normal interaction record, but it will
auto-narrow the interaction time period to only include the
synthetic gesture event output by Chrome. This is typically use to
reduce noise in gesture-based analysis (e.g., analysis for a
swipe/scroll).
The interaction record label will be prepended with 'Gesture_'.
e.g:
with action_runner.CreateGestureInteraction('Scroll-1'):
action_runner.ScrollPage()
Args:
label: A label for this particular interaction. This can be any
user-defined string, but must not contain '/'.
repeatable: Whether other interactions may use the same logical name
as this interaction. All interactions with the same logical name must
have the same flags.
Returns:
An instance of action_runner.Interaction
"""
return self.CreateInteraction('Gesture_' + label, repeatable)
def NavigateToPage(self, page, timeout_in_seconds=60):
"""Navigates to the given page.
......@@ -624,6 +688,18 @@ class Interaction(object):
self._flags = flags
self._started = False
def __enter__(self):
self.Begin()
return self
def __exit__(self, exc_type, exc_value, traceback):
if exc_value is None:
self.End()
else:
logging.warning(
'Exception was raised in the with statement block, the end of '
'interaction record is not marked.')
def Begin(self):
assert not self._started
self._started = True
......
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