Index: tools/perf/page_sets/news_stories.py |
diff --git a/tools/perf/page_sets/news_stories.py b/tools/perf/page_sets/news_stories.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..553b6a9561b57dd14d159d994e1f77cd9fc94639 |
--- /dev/null |
+++ b/tools/perf/page_sets/news_stories.py |
@@ -0,0 +1,213 @@ |
+# Copyright 2016 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 sys |
+ |
+from telemetry.page import page |
+ |
+from telemetry.core import discover |
+from telemetry import story |
+ |
+_ALL_PLATFORMS = frozenset({'desktop', 'mobile'}) |
+_DESKTOP_ONLY = frozenset({'desktop'}) |
+_MOBILE_ONLY = frozenset({'mobile'}) |
+_NO_PLATFORMS = frozenset() |
+_NEWS_ITEM_READ_TIME_IN_SECONDS = 3 |
+ |
+class _NewsStory(page.Page): |
petrcermak
2016/07/07 14:55:56
I can see that this class is modelled very closely
ulan
2016/07/07 17:34:38
Sounds good. I will do this change tomorrow.
|
+ """Abstract base class for news user stories. |
+ |
+ A news story imitates browsing a news website: |
+ 1. Load the main page. |
+ 2. Open and scroll the first news item. |
+ 3. Go back to the main page and scroll it. |
+ 4. Open and scroll the second news item. |
+ 5. Go back to the main page and scroll it. |
+ 6. etc. |
+ """ |
+ |
+ NAME = NotImplemented |
+ URL = NotImplemented |
+ NEWS_ITEM_SELECTOR = NotImplemented |
+ NEWS_ITEMS_TO_VISIT = 4 |
+ SUPPORTED_PLATFORMS = _ALL_PLATFORMS |
+ IS_SINGLE_PAGE_APP = False |
+ |
+ def __init__(self, story_set): |
+ super(_NewsStory, self).__init__( |
+ page_set=story_set, name=self.NAME, url=self.URL) |
+ |
+ def RunPageInteractions(self, action_runner): |
+ action_runner.tab.WaitForDocumentReadyStateToBeComplete() |
+ self._DidLoadDocument(action_runner) |
+ for i in xrange(self.NEWS_ITEMS_TO_VISIT): |
+ self._ClickNewsItem(action_runner, i) |
+ self._ReadNewsItem(action_runner) |
+ self._NavigateBack(action_runner) |
+ self._ScrollMainPage(action_runner) |
+ |
+ def _NewsItem(self, index): |
+ return 'document.querySelectorAll(\'%s\')[%d]' % ( |
+ self.NEWS_ITEM_SELECTOR, index) |
+ |
+ def _DidLoadDocument(self, action_runner): |
+ pass |
+ |
+ def _WaitForNavigation(self, action_runner): |
+ if not self.IS_SINGLE_PAGE_APP: |
+ action_runner.WaitForNavigate() |
+ |
+ def _ClickNewsItem(self, action_runner, index): |
+ action_runner.WaitForElement(element_function=self._NewsItem(index)) |
+ action_runner.ClickElement(element_function=self._NewsItem(index)) |
+ self._WaitForNavigation(action_runner) |
+ |
+ def _ReadNewsItem(self, action_runner): |
+ action_runner.tab.WaitForDocumentReadyStateToBeComplete() |
+ action_runner.Wait(_NEWS_ITEM_READ_TIME_IN_SECONDS) |
+ action_runner.RepeatableBrowserDrivenScroll(repeat_count=2) |
+ |
+ def _NavigateBack(self, action_runner): |
+ action_runner.ExecuteJavaScript('window.history.back()') |
+ self._WaitForNavigation(action_runner) |
+ |
+ def _ScrollMainPage(self, action_runner): |
+ action_runner.tab.WaitForDocumentReadyStateToBeComplete() |
+ action_runner.RepeatableBrowserDrivenScroll(repeat_count=0) |
+ |
+ |
+def IterAllStoryClasses(): |
+ # Sort the classes by their names so that their order is stable and |
+ # deterministic. |
+ for unused_cls_name, cls in sorted(discover.DiscoverClassesInModule( |
+ module=sys.modules[__name__], |
+ base_class=_NewsStory, |
+ index_by_class_name=True).iteritems()): |
+ yield cls |
+ |
+ |
+############################################################################## |
+# News stories. |
+############################################################################## |
+ |
+ |
+class RedditDesktopStory(_NewsStory): |
+ """The top website in http://www.alexa.com/topsites/category/News""" |
+ NAME = 'reddit' |
+ URL = 'https://www.reddit.com/top/?sort=top&t=week' |
+ SUPPORTED_PLATFORMS = _DESKTOP_ONLY |
+ NEWS_ITEM_SELECTOR = '.thing .title > a' |
+ |
+ |
+class RedditMobileStory(_NewsStory): |
+ """The top website in http://www.alexa.com/topsites/category/News""" |
+ NAME = 'reddit' |
+ URL = 'https://m.reddit.com/?sort=top&time=week' |
+ SUPPORTED_PLATFORMS = _MOBILE_ONLY |
+ NEWS_ITEM_SELECTOR = '.PostHeader__post-title-line' |
+ IS_SINGLE_PAGE_APP = True |
+ |
+ |
+class CnnStory(_NewsStory): |
+ """The second top website in http://www.alexa.com/topsites/category/News""" |
+ NAME = 'cnn' |
+ URL = 'http://edition.cnn.com/' |
+ NEWS_ITEM_SELECTOR = '.cd__content > h3 > a' |
+ # TODO(ulan): Enable this story on mobile once it uses less memory and |
+ # does not crash with OOM. |
+ SUPPORTED_PLATFORMS = _DESKTOP_ONLY |
+ |
+ |
+class NytimesMobileStory(_NewsStory): |
+ """The third top website in http://www.alexa.com/topsites/category/News""" |
+ NAME = 'nytimes' |
+ URL = 'http://mobile.nytimes.com' |
+ SUPPORTED_PLATFORMS = _MOBILE_ONLY |
+ NEWS_ITEM_SELECTOR = '.sfgAsset-link' |
+ # Visiting more items causes OOM. |
+ NEWS_ITEMS_TO_VISIT = 2 |
+ |
+ |
+class NytimesDesktopStory(_NewsStory): |
+ """The third top website in http://www.alexa.com/topsites/category/News""" |
+ NAME = 'nytimes' |
+ URL = 'http://www.nytimes.com' |
+ SUPPORTED_PLATFORMS = _DESKTOP_ONLY |
+ NEWS_ITEM_SELECTOR = '.story-heading > a' |
+ |
+ |
+class HackerNewsStory(_NewsStory): |
+ NAME = 'hackernews' |
+ URL = 'https://news.ycombinator.com' |
+ NEWS_ITEM_SELECTOR = '.athing .title > a' |
+ |
+ |
+# Facebook on desktop is not interesting because it embeds post comments |
+# directly in the main timeline. |
+class FacebookMobileStory(_NewsStory): |
+ NAME = 'facebook' |
+ URL = 'https://facebook.com/natgeo' |
+ NEWS_ITEM_SELECTOR = 'article ._5msj' |
+ SUPPORTED_PLATFORMS = _MOBILE_ONLY |
+ |
+ |
+class TwitterMobileStory(_NewsStory): |
+ NAME = 'twitter' |
+ URL = 'https://mobile.twitter.com/cnnbrk' |
+ NEWS_ITEM_SELECTOR = '.Tweet-text' |
+ SUPPORTED_PLATFORMS = _MOBILE_ONLY |
+ |
+ |
+class TwitterDesktopStory(_NewsStory): |
+ NAME = 'twitter' |
+ URL = 'https://twitter.com/cnnbrk' |
+ NEWS_ITEM_SELECTOR = '.tweet-text' |
+ SUPPORTED_PLATFORMS = _DESKTOP_ONLY |
+ IS_SINGLE_PAGE_APP = True |
+ |
+ |
+class WashingtonPostMobileStory(_NewsStory): |
+ """Progressive website""" |
+ NAME = 'washingtonpost' |
+ URL = 'https://www.washingtonpost.com/pwa' |
+ SUPPORTED_PLATFORMS = _MOBILE_ONLY |
+ NEWS_ITEM_SELECTOR = '.hed > a' |
+ IS_SINGLE_PAGE_APP = True |
+ |
+ def _DidLoadDocument(self, action_runner): |
+ # Close the popup window. |
+ action_runner.ClickElement(selector='.close') |
+ |
+ |
+class WashingtonPostDesktopStory(_NewsStory): |
+ NAME = 'washingtonpost' |
+ URL = 'https://www.washingtonpost.com' |
+ SUPPORTED_PLATFORMS = _DESKTOP_ONLY |
+ NEWS_ITEM_SELECTOR = '.headline > a' |
+ |
+ |
+############################################################################## |
+# News story sets. |
+############################################################################## |
+ |
+ |
+class _NewsStorySet(story.StorySet): |
+ PLATFORM = NotImplemented |
+ |
+ def __init__(self): |
+ super(_NewsStorySet, self).__init__( |
+ archive_data_file=('../data/news_%s.json' % self.PLATFORM), |
+ cloud_storage_bucket=story.PARTNER_BUCKET) |
+ for story_class in IterAllStoryClasses(): |
+ if self.PLATFORM not in story_class.SUPPORTED_PLATFORMS: |
+ continue |
+ self.AddStory(story_class(self)) |
+ |
+ |
+class DesktopNewsStorySet(_NewsStorySet): |
+ PLATFORM = 'desktop' |
+ |
+ |
+class MobileNewsStorySet(_NewsStorySet): |
+ PLATFORM = 'mobile' |