Chromium Code Reviews| 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' |