Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / page / page_test.py
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.
4
5 from telemetry.core import command_line
6
7 from telemetry.page import test_expectations
8 from telemetry.page.actions import action_runner as action_runner_module
9 from telemetry.page.actions import interact
10
11
12 class Failure(Exception):
13   """Exception that can be thrown from PageMeasurement to indicate an
14   undesired but designed-for problem."""
15
16
17 class TestNotSupportedOnPlatformFailure(Failure):
18   """Exception that can be thrown to indicate that a certain feature required
19   to run the test is not available on the platform, hardware configuration, or
20   browser version."""
21
22
23 class PageTest(command_line.Command):
24   """A class styled on unittest.TestCase for creating page-specific tests."""
25
26   options = {}
27
28   def __init__(self,
29                action_name_to_run='',
30                needs_browser_restart_after_each_page=False,
31                discard_first_result=False,
32                clear_cache_before_each_run=False,
33                attempts=3,
34                max_failures=None,
35                max_errors=None):
36     super(PageTest, self).__init__()
37
38     self.options = None
39     if action_name_to_run:
40       assert action_name_to_run.startswith('Run') \
41           and '_' not in action_name_to_run, \
42           ('Wrong way of naming action_name_to_run. By new convention,'
43            'action_name_to_run must start with Run- prefix and in CamelCase.')
44     self._action_name_to_run = action_name_to_run
45     self._needs_browser_restart_after_each_page = (
46         needs_browser_restart_after_each_page)
47     self._discard_first_result = discard_first_result
48     self._clear_cache_before_each_run = clear_cache_before_each_run
49     self._close_tabs_before_run = True
50     self._attempts = attempts
51     self._max_failures = max_failures
52     self._max_errors = max_errors
53     assert self._attempts > 0, 'Test attempts must be greater than 0'
54     # If the test overrides the TabForPage method, it is considered a multi-tab
55     # test.  The main difference between this and a single-tab test is that we
56     # do not attempt recovery for the former if a tab or the browser crashes,
57     # because we don't know the current state of tabs (how many are open, etc.)
58     self.is_multi_tab_test = (self.__class__ is not PageTest and
59                               self.TabForPage.__func__ is not
60                               self.__class__.__bases__[0].TabForPage.__func__)
61     # _exit_requested is set to true when the test requests an early exit.
62     self._exit_requested = False
63
64   @classmethod
65   def SetArgumentDefaults(cls, parser):
66     parser.set_defaults(**cls.options)
67
68   @property
69   def discard_first_result(self):
70     """When set to True, the first run of the test is discarded.  This is
71     useful for cases where it's desirable to have some test resource cached so
72     the first run of the test can warm things up. """
73     return self._discard_first_result
74
75   @discard_first_result.setter
76   def discard_first_result(self, discard):
77     self._discard_first_result = discard
78
79   @property
80   def clear_cache_before_each_run(self):
81     """When set to True, the browser's disk and memory cache will be cleared
82     before each run."""
83     return self._clear_cache_before_each_run
84
85   @property
86   def close_tabs_before_run(self):
87     """When set to True, all tabs are closed before running the test for the
88     first time."""
89     return self._close_tabs_before_run
90
91   @close_tabs_before_run.setter
92   def close_tabs_before_run(self, close_tabs):
93     self._close_tabs_before_run = close_tabs
94
95   @property
96   def attempts(self):
97     """Maximum number of times test will be attempted."""
98     return self._attempts
99
100   @attempts.setter
101   def attempts(self, count):
102     assert self._attempts > 0, 'Test attempts must be greater than 0'
103     self._attempts = count
104
105   @property
106   def max_failures(self):
107     """Maximum number of failures allowed for the page set."""
108     return self._max_failures
109
110   @max_failures.setter
111   def max_failures(self, count):
112     self._max_failures = count
113
114   @property
115   def max_errors(self):
116     """Maximum number of errors allowed for the page set."""
117     return self._max_errors
118
119   @max_errors.setter
120   def max_errors(self, count):
121     self._max_errors = count
122
123   def Run(self, args):
124     # Define this method to avoid pylint errors.
125     # TODO(dtu): Make this actually run the test with args.page_set.
126     pass
127
128   def RestartBrowserBeforeEachPage(self):
129     """ Should the browser be restarted for the page?
130
131     This returns true if the test needs to unconditionally restart the
132     browser for each page. It may be called before the browser is started.
133     """
134     return self._needs_browser_restart_after_each_page
135
136   def StopBrowserAfterPage(self, browser, page):  # pylint: disable=W0613
137     """Should the browser be stopped after the page is run?
138
139     This is called after a page is run to decide whether the browser needs to
140     be stopped to clean up its state. If it is stopped, then it will be
141     restarted to run the next page.
142
143     A test that overrides this can look at both the page and the browser to
144     decide whether it needs to stop the browser.
145     """
146     return False
147
148   def CustomizeBrowserOptions(self, options):
149     """Override to add test-specific options to the BrowserOptions object"""
150
151   def CustomizeBrowserOptionsForSinglePage(self, page, options):
152     """Set options specific to the test and the given page.
153
154     This will be called with the current page when the browser is (re)started.
155     Changing options at this point only makes sense if the browser is being
156     restarted for each page. Note that if page has a startup_url, the browser
157     will always be restarted for each run.
158     """
159     if page.startup_url:
160       options.browser_options.startup_url = page.startup_url
161
162   def WillStartBrowser(self, browser):
163     """Override to manipulate the browser environment before it launches."""
164
165   def DidStartBrowser(self, browser):
166     """Override to customize the browser right after it has launched."""
167
168   def CanRunForPage(self, page):  # pylint: disable=W0613
169     """Override to customize if the test can be ran for the given page."""
170     if self._action_name_to_run:
171       return hasattr(page, self._action_name_to_run)
172     return True
173
174   def WillRunTest(self, options):
175     """Override to do operations before the page set(s) are navigated."""
176     self.options = options
177
178   def DidRunTest(self, browser, results): # pylint: disable=W0613
179     """Override to do operations after all page set(s) are completed.
180
181     This will occur before the browser is torn down.
182     """
183     self.options = None
184
185   def WillRunPageRepeats(self, page):
186     """Override to do operations before each page is iterated over."""
187
188   def DidRunPageRepeats(self, page):
189     """Override to do operations after each page is iterated over."""
190
191   def DidStartHTTPServer(self, tab):
192     """Override to do operations after the HTTP server is started."""
193
194   def WillNavigateToPage(self, page, tab):
195     """Override to do operations before the page is navigated, notably Telemetry
196     will already have performed the following operations on the browser before
197     calling this function:
198     * Ensure only one tab is open.
199     * Call WaitForDocumentReadyStateToComplete on the tab."""
200
201   def DidNavigateToPage(self, page, tab):
202     """Override to do operations right after the page is navigated and after
203     all waiting for completion has occurred."""
204
205   def WillRunActions(self, page, tab):
206     """Override to do operations before running the actions on the page."""
207
208   def DidRunActions(self, page, tab):
209     """Override to do operations after running the actions on the page."""
210
211   def CleanUpAfterPage(self, page, tab):
212     """Called after the test run method was run, even if it failed."""
213
214   def CreateExpectations(self, page_set):   # pylint: disable=W0613
215     """Override to make this test generate its own expectations instead of
216     any that may have been defined in the page set."""
217     return test_expectations.TestExpectations()
218
219   def TabForPage(self, page, browser):   # pylint: disable=W0613
220     """Override to select a different tab for the page.  For instance, to
221     create a new tab for every page, return browser.tabs.New()."""
222     return browser.tabs[0]
223
224   def ValidatePageSet(self, page_set):
225     """Override to examine the page set before the test run.  Useful for
226     example to validate that the pageset can be used with the test."""
227
228   def ValidatePage(self, page, tab, results):
229     """Override to check the actual test assertions.
230
231     This is where most your test logic should go."""
232     raise NotImplementedError()
233
234   def RunPage(self, page, tab, results):
235     # Run actions.
236     interactive = self.options and self.options.interactive
237     action_runner = action_runner_module.ActionRunner(page, tab, self)
238     self.WillRunActions(page, tab)
239     if interactive:
240       action_runner.RunAction(interact.InteractAction())
241     else:
242       self._RunMethod(page, self._action_name_to_run, action_runner)
243     self.DidRunActions(page, tab)
244
245     # Run validator.
246     self.ValidatePage(page, tab, results)
247
248   def _RunMethod(self, page, method_name, action_runner):
249     if hasattr(page, method_name):
250       run_method = getattr(page, method_name)
251       run_method(action_runner)
252
253   def RunNavigateSteps(self, page, tab):
254     """Navigates the tab to the page URL attribute.
255
256     Runs the 'navigate_steps' page attribute as a compound action.
257     """
258     action_runner = action_runner_module.ActionRunner(page, tab, None)
259     page.RunNavigateSteps(action_runner)
260
261   def IsExiting(self):
262     return self._exit_requested
263
264   def RequestExit(self):
265     self._exit_requested = True
266
267   @property
268   def action_name_to_run(self):
269     return self._action_name_to_run