mirror of
				https://github.com/ARM-software/workload-automation.git
				synced 2025-11-04 09:02:12 +00:00 
			
		
		
		
	Merge pull request #227 from jimboatarm/upstream-youtube
Add Youtube workload
This commit is contained in:
		
							
								
								
									
										90
									
								
								wlauto/workloads/youtube/__init__.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										90
									
								
								wlauto/workloads/youtube/__init__.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,90 @@
 | 
			
		||||
#    Copyright 2014-2016 ARM Limited
 | 
			
		||||
#
 | 
			
		||||
# Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
# you may not use this file except in compliance with the License.
 | 
			
		||||
# You may obtain a copy of the License at
 | 
			
		||||
#
 | 
			
		||||
#     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
#
 | 
			
		||||
# Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
# distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
# See the License for the specific language governing permissions and
 | 
			
		||||
# limitations under the License.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
from wlauto import AndroidUxPerfWorkload, Parameter
 | 
			
		||||
from wlauto.exceptions import WorkloadError
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Youtube(AndroidUxPerfWorkload):
 | 
			
		||||
 | 
			
		||||
    name = 'youtube'
 | 
			
		||||
    package = 'com.google.android.youtube'
 | 
			
		||||
    min_apk_version = '11.19.56'
 | 
			
		||||
    max_apk_version = None  # works with latest (11.33.58) at time of publishing this
 | 
			
		||||
    activity = ''
 | 
			
		||||
    description = '''
 | 
			
		||||
    A workload to perform standard productivity tasks within YouTube.
 | 
			
		||||
 | 
			
		||||
    The workload plays a video from the app, determined by the ``video_source`` parameter.
 | 
			
		||||
    While the video is playing, a some common actions are done such as video seeking, pausing
 | 
			
		||||
    playback and navigating the comments section.
 | 
			
		||||
 | 
			
		||||
    Test description:
 | 
			
		||||
    The ``video_source`` parameter determines where the video to be played will be found
 | 
			
		||||
    in the app. Possible values are ``search``, ``home``, ``my_videos``, and ``trending``.
 | 
			
		||||
    -A. search - Goes to the search view, does a search for the given term, and plays the
 | 
			
		||||
        first video in the results. The parameter ``search_term`` must also be provided
 | 
			
		||||
        in the agenda for this to work. This is the default mode.
 | 
			
		||||
    -B. home - Scrolls down once on the app's home page to avoid ads (if present, would be
 | 
			
		||||
        first video), then select and plays the video that appears at the top of the list.
 | 
			
		||||
    -C. my_videos - Goes to the 'My Videos' section of the user's account page and plays a
 | 
			
		||||
        video from there. The user must have at least one uploaded video for this to work.
 | 
			
		||||
    -D. trending - Goes to the 'Trending Videos' section of the app, and plays the first
 | 
			
		||||
        video in the trending videos list.
 | 
			
		||||
 | 
			
		||||
    For the selected video source, the following test steps are performed:
 | 
			
		||||
    1.  Navigate to the general app settings page to disable autoplay. This improves test
 | 
			
		||||
        stability and predictability by preventing screen transition to load a new video
 | 
			
		||||
        while in the middle of the test.
 | 
			
		||||
    2.  Select the video from the source specified above, and dismiss any potential embedded
 | 
			
		||||
        advert that may pop-up before the actual video.
 | 
			
		||||
    3.  Let the video play for a few seconds, pause it, then resume.
 | 
			
		||||
    4.  Expand the info card that shows video metadata, then collapse it again.
 | 
			
		||||
    5.  Scroll down to the end of related videos and comments under the info card, and then
 | 
			
		||||
        back up to the start. A maximum of 5 swipe actions is performed in either direction.
 | 
			
		||||
    '''
 | 
			
		||||
 | 
			
		||||
    parameters = [
 | 
			
		||||
        Parameter('video_source', kind=str, default='search',
 | 
			
		||||
                  allowed_values=['home', 'my_videos', 'search', 'trending'],
 | 
			
		||||
                  description='''
 | 
			
		||||
                  Determines where to play the video from. This can either be from the
 | 
			
		||||
                  YouTube home, my videos section, trending videos or found in search.
 | 
			
		||||
                  '''),
 | 
			
		||||
        Parameter('search_term', kind=str,
 | 
			
		||||
                  default='Big Buck Bunny 60fps 4K - Official Blender Foundation Short Film',
 | 
			
		||||
                  description='''
 | 
			
		||||
                  The search term to use when ``video_source`` is set to ``search``. Ignored otherwise.
 | 
			
		||||
                  '''),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    view = [
 | 
			
		||||
        package + '/com.google.android.apps.youtube.app.WatchWhileActivity',
 | 
			
		||||
        package + '/com.google.android.apps.youtube.app.honeycomb.SettingsActivity',
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    requires_network = True
 | 
			
		||||
 | 
			
		||||
    def __init__(self, device, **kwargs):
 | 
			
		||||
        super(Youtube, self).__init__(device, **kwargs)
 | 
			
		||||
        self.run_timeout = 300
 | 
			
		||||
 | 
			
		||||
    def validate(self):
 | 
			
		||||
        if self.video_source == 'search' and not self.search_term:
 | 
			
		||||
            raise WorkloadError("Param 'search_term' must be specified when video source is 'search'")
 | 
			
		||||
 | 
			
		||||
        self.uiauto_params['package'] = self.package
 | 
			
		||||
        self.uiauto_params['video_source'] = self.video_source
 | 
			
		||||
        self.uiauto_params['search_term'] = self.search_term.replace(' ', '0space0')
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								wlauto/workloads/youtube/com.arm.wlauto.uiauto.youtube.jar
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								wlauto/workloads/youtube/com.arm.wlauto.uiauto.youtube.jar
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										39
									
								
								wlauto/workloads/youtube/uiauto/build.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										39
									
								
								wlauto/workloads/youtube/uiauto/build.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
# CD into build dir if possible - allows building from any directory
 | 
			
		||||
script_path='.'
 | 
			
		||||
if `readlink -f $0 &>/dev/null`; then
 | 
			
		||||
    script_path=`readlink -f $0 2>/dev/null`
 | 
			
		||||
fi
 | 
			
		||||
script_dir=`dirname $script_path`
 | 
			
		||||
cd $script_dir
 | 
			
		||||
 | 
			
		||||
# Ensure build.xml exists before starting
 | 
			
		||||
if [[ ! -f build.xml ]]; then
 | 
			
		||||
    echo 'Ant build.xml file not found! Check that you are in the right directory.'
 | 
			
		||||
    exit 9
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Copy base classes from wlauto dist
 | 
			
		||||
class_dir=bin/classes/com/arm/wlauto/uiauto
 | 
			
		||||
base_classes=`python -c "import os, wlauto; print os.path.join(os.path.dirname(wlauto.__file__), 'common', 'android', '*.class')"`
 | 
			
		||||
mkdir -p $class_dir
 | 
			
		||||
cp $base_classes $class_dir
 | 
			
		||||
 | 
			
		||||
# Build and return appropriate exit code if failed
 | 
			
		||||
ant build
 | 
			
		||||
exit_code=$?
 | 
			
		||||
if [[ $exit_code -ne 0 ]]; then
 | 
			
		||||
    echo "ERROR: 'ant build' exited with code $exit_code"
 | 
			
		||||
    exit $exit_code
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# If successful move JAR file to workload folder (overwrite previous)
 | 
			
		||||
package=com.arm.wlauto.uiauto.youtube.jar
 | 
			
		||||
rm -f ../$package
 | 
			
		||||
if [[ -f bin/$package ]]; then
 | 
			
		||||
    cp bin/$package ..
 | 
			
		||||
else
 | 
			
		||||
    echo 'ERROR: UiAutomator JAR could not be found!'
 | 
			
		||||
    exit 9
 | 
			
		||||
fi
 | 
			
		||||
							
								
								
									
										92
									
								
								wlauto/workloads/youtube/uiauto/build.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								wlauto/workloads/youtube/uiauto/build.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project name="com.arm.wlauto.uiauto.youtube" default="help">
 | 
			
		||||
 | 
			
		||||
    <!-- The local.properties file is created and updated by the 'android' tool.
 | 
			
		||||
         It contains the path to the SDK. It should *NOT* be checked into
 | 
			
		||||
         Version Control Systems. -->
 | 
			
		||||
    <property file="local.properties" />
 | 
			
		||||
 | 
			
		||||
    <!-- The ant.properties file can be created by you. It is only edited by the
 | 
			
		||||
         'android' tool to add properties to it.
 | 
			
		||||
         This is the place to change some Ant specific build properties.
 | 
			
		||||
         Here are some properties you may want to change/update:
 | 
			
		||||
 | 
			
		||||
         source.dir
 | 
			
		||||
             The name of the source directory. Default is 'src'.
 | 
			
		||||
         out.dir
 | 
			
		||||
             The name of the output directory. Default is 'bin'.
 | 
			
		||||
 | 
			
		||||
         For other overridable properties, look at the beginning of the rules
 | 
			
		||||
         files in the SDK, at tools/ant/build.xml
 | 
			
		||||
 | 
			
		||||
         Properties related to the SDK location or the project target should
 | 
			
		||||
         be updated using the 'android' tool with the 'update' action.
 | 
			
		||||
 | 
			
		||||
         This file is an integral part of the build system for your
 | 
			
		||||
         application and should be checked into Version Control Systems.
 | 
			
		||||
 | 
			
		||||
         -->
 | 
			
		||||
    <property file="ant.properties" />
 | 
			
		||||
 | 
			
		||||
    <!-- if sdk.dir was not set from one of the property file, then
 | 
			
		||||
         get it from the ANDROID_HOME env var.
 | 
			
		||||
         This must be done before we load project.properties since
 | 
			
		||||
         the proguard config can use sdk.dir -->
 | 
			
		||||
    <property environment="env" />
 | 
			
		||||
    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
 | 
			
		||||
        <isset property="env.ANDROID_HOME" />
 | 
			
		||||
    </condition>
 | 
			
		||||
 | 
			
		||||
    <!-- The project.properties file is created and updated by the 'android'
 | 
			
		||||
         tool, as well as ADT.
 | 
			
		||||
 | 
			
		||||
         This contains project specific properties such as project target, and library
 | 
			
		||||
         dependencies. Lower level build properties are stored in ant.properties
 | 
			
		||||
         (or in .classpath for Eclipse projects).
 | 
			
		||||
 | 
			
		||||
         This file is an integral part of the build system for your
 | 
			
		||||
         application and should be checked into Version Control Systems. -->
 | 
			
		||||
    <loadproperties srcFile="project.properties" />
 | 
			
		||||
 | 
			
		||||
    <!-- quick check on sdk.dir -->
 | 
			
		||||
    <fail
 | 
			
		||||
            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
 | 
			
		||||
            unless="sdk.dir"
 | 
			
		||||
    />
 | 
			
		||||
 | 
			
		||||
    <!--
 | 
			
		||||
        Import per project custom build rules if present at the root of the project.
 | 
			
		||||
        This is the place to put custom intermediary targets such as:
 | 
			
		||||
            -pre-build
 | 
			
		||||
            -pre-compile
 | 
			
		||||
            -post-compile (This is typically used for code obfuscation.
 | 
			
		||||
                           Compiled code location: ${out.classes.absolute.dir}
 | 
			
		||||
                           If this is not done in place, override ${out.dex.input.absolute.dir})
 | 
			
		||||
            -post-package
 | 
			
		||||
            -post-build
 | 
			
		||||
            -pre-clean
 | 
			
		||||
    -->
 | 
			
		||||
    <import file="custom_rules.xml" optional="true" />
 | 
			
		||||
 | 
			
		||||
    <!-- Import the actual build file.
 | 
			
		||||
 | 
			
		||||
         To customize existing targets, there are two options:
 | 
			
		||||
         - Customize only one target:
 | 
			
		||||
             - copy/paste the target into this file, *before* the
 | 
			
		||||
               <import> task.
 | 
			
		||||
             - customize it to your needs.
 | 
			
		||||
         - Customize the whole content of build.xml
 | 
			
		||||
             - copy/paste the content of the rules files (minus the top node)
 | 
			
		||||
               into this file, replacing the <import> task.
 | 
			
		||||
             - customize to your needs.
 | 
			
		||||
 | 
			
		||||
         ***********************
 | 
			
		||||
         ****** IMPORTANT ******
 | 
			
		||||
         ***********************
 | 
			
		||||
         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
 | 
			
		||||
         in order to avoid having your file be overridden by tools such as "android update project"
 | 
			
		||||
    -->
 | 
			
		||||
    <!-- version-tag: VERSION_TAG -->
 | 
			
		||||
    <import file="${sdk.dir}/tools/ant/uibuild.xml" />
 | 
			
		||||
 | 
			
		||||
</project>
 | 
			
		||||
							
								
								
									
										14
									
								
								wlauto/workloads/youtube/uiauto/project.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								wlauto/workloads/youtube/uiauto/project.properties
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
# This file is automatically generated by Android Tools.
 | 
			
		||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
 | 
			
		||||
#
 | 
			
		||||
# This file must be checked in Version Control Systems.
 | 
			
		||||
#
 | 
			
		||||
# To customize properties used by the Ant build system edit
 | 
			
		||||
# "ant.properties", and override values to adapt the script to your
 | 
			
		||||
# project structure.
 | 
			
		||||
#
 | 
			
		||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
 | 
			
		||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
 | 
			
		||||
 | 
			
		||||
# Project target.
 | 
			
		||||
target=android-18
 | 
			
		||||
@@ -0,0 +1,239 @@
 | 
			
		||||
/*    Copyright 2014-2016 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package com.arm.wlauto.uiauto.youtube;
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.os.SystemClock;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
 | 
			
		||||
// Import the uiautomator libraries
 | 
			
		||||
import com.android.uiautomator.core.UiObject;
 | 
			
		||||
import com.android.uiautomator.core.UiScrollable;
 | 
			
		||||
import com.android.uiautomator.core.UiSelector;
 | 
			
		||||
 | 
			
		||||
import com.arm.wlauto.uiauto.UxPerfUiAutomation;
 | 
			
		||||
 | 
			
		||||
import static com.arm.wlauto.uiauto.BaseUiAutomation.FindByCriteria.BY_ID;
 | 
			
		||||
import static com.arm.wlauto.uiauto.BaseUiAutomation.FindByCriteria.BY_TEXT;
 | 
			
		||||
import static com.arm.wlauto.uiauto.BaseUiAutomation.FindByCriteria.BY_DESC;
 | 
			
		||||
 | 
			
		||||
public class UiAutomation extends UxPerfUiAutomation {
 | 
			
		||||
 | 
			
		||||
    public static final String CLASS_BUTTON = "android.widget.Button";
 | 
			
		||||
    public static final String CLASS_TEXT_VIEW = "android.widget.TextView";
 | 
			
		||||
 | 
			
		||||
    public static final int WAIT_TIMEOUT_1SEC = 1000;
 | 
			
		||||
    public static final int WAIT_TIMEOUT_5SEC = 5000;
 | 
			
		||||
    public static final int VIDEO_SLEEP_SECONDS = 3;
 | 
			
		||||
    public static final int LIST_SWIPE_COUNT = 5;
 | 
			
		||||
    public static final String SOURCE_MY_VIDEOS = "my_videos";
 | 
			
		||||
    public static final String SOURCE_SEARCH = "search";
 | 
			
		||||
    public static final String SOURCE_TRENDING = "trending";
 | 
			
		||||
 | 
			
		||||
    protected ActionLogger logger;
 | 
			
		||||
    protected Bundle parameters;
 | 
			
		||||
    protected String packageName;
 | 
			
		||||
    protected String packageID;
 | 
			
		||||
    protected String searchTerm;
 | 
			
		||||
 | 
			
		||||
    public void runUiAutomation() throws Exception {
 | 
			
		||||
        parameters = getParams();
 | 
			
		||||
        packageName = parameters.getString("package");
 | 
			
		||||
        packageID = packageName + ":id/";
 | 
			
		||||
        searchTerm = parameters.getString("search_term");
 | 
			
		||||
        if (searchTerm != null) {
 | 
			
		||||
            searchTerm = searchTerm.replaceAll("0space0", " ");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        setScreenOrientation(ScreenOrientation.NATURAL);
 | 
			
		||||
        clearFirstRunDialogues();
 | 
			
		||||
        disableAutoplay();
 | 
			
		||||
        testPlayVideo(parameters.getString("video_source"), searchTerm);
 | 
			
		||||
        unsetScreenOrientation();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void clearFirstRunDialogues() throws Exception {
 | 
			
		||||
        UiObject laterButton = new UiObject(new UiSelector().textContains("Later").className(CLASS_TEXT_VIEW));
 | 
			
		||||
        if (laterButton.waitForExists(WAIT_TIMEOUT_1SEC)) {
 | 
			
		||||
           laterButton.click();
 | 
			
		||||
        }
 | 
			
		||||
        UiObject cancelButton = new UiObject(new UiSelector().textContains("Cancel").className(CLASS_BUTTON));
 | 
			
		||||
        if (cancelButton.waitForExists(WAIT_TIMEOUT_1SEC)) {
 | 
			
		||||
            cancelButton.click();
 | 
			
		||||
        }
 | 
			
		||||
        UiObject skipButton = new UiObject(new UiSelector().textContains("Skip").className(CLASS_TEXT_VIEW));
 | 
			
		||||
        if (skipButton.waitForExists(WAIT_TIMEOUT_1SEC)) {
 | 
			
		||||
            skipButton.click();
 | 
			
		||||
        }
 | 
			
		||||
        UiObject gotItButton = new UiObject(new UiSelector().textContains("Got it").className(CLASS_BUTTON));
 | 
			
		||||
        if (gotItButton.waitForExists(WAIT_TIMEOUT_1SEC)) {
 | 
			
		||||
            gotItButton.click();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void disableAutoplay() throws Exception {
 | 
			
		||||
        clickUiObject(BY_DESC, "More options");
 | 
			
		||||
        startMeasurements("goto_settings");
 | 
			
		||||
        clickUiObject(BY_TEXT, "Settings", true);
 | 
			
		||||
        endMeasurements("goto_settings");
 | 
			
		||||
        startMeasurements("goto_settings_general");
 | 
			
		||||
        clickUiObject(BY_TEXT, "General", true);
 | 
			
		||||
        endMeasurements("goto_settings_general");
 | 
			
		||||
 | 
			
		||||
        // Don't fail fatally if autoplay toggle cannot be found
 | 
			
		||||
        UiObject autoplayToggle = new UiObject(new UiSelector().textContains("Autoplay"));
 | 
			
		||||
        if (autoplayToggle.waitForExists(WAIT_TIMEOUT_1SEC)) {
 | 
			
		||||
            autoplayToggle.click();
 | 
			
		||||
        }
 | 
			
		||||
        getUiDevice().pressBack();
 | 
			
		||||
 | 
			
		||||
        // Tablet devices use a split with General in the left pane and Autoplay in the right so no
 | 
			
		||||
        // need to click back twice
 | 
			
		||||
        UiObject generalButton = new UiObject(new UiSelector().textContains("General").className(CLASS_TEXT_VIEW));
 | 
			
		||||
        if (generalButton.exists()) {
 | 
			
		||||
            getUiDevice().pressBack();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void testPlayVideo(String source, String searchTerm) throws Exception {
 | 
			
		||||
        if (SOURCE_MY_VIDEOS.equalsIgnoreCase(source)) {
 | 
			
		||||
            startMeasurements("goto_account");
 | 
			
		||||
            clickUiObject(BY_DESC, "Account");
 | 
			
		||||
            endMeasurements("goto_account");
 | 
			
		||||
            startMeasurements("goto_my_videos");
 | 
			
		||||
            clickUiObject(BY_TEXT, "My Videos", true);
 | 
			
		||||
            endMeasurements("goto_my_videos");
 | 
			
		||||
 | 
			
		||||
            startMeasurements("play_from_my_videos");
 | 
			
		||||
            clickUiObject(BY_ID, packageID + "thumbnail", true);
 | 
			
		||||
            endMeasurements("play_from_my_videos");
 | 
			
		||||
 | 
			
		||||
        } else if (SOURCE_SEARCH.equalsIgnoreCase(source)) {
 | 
			
		||||
            startMeasurements("goto_search");
 | 
			
		||||
            clickUiObject(BY_DESC, "Search");
 | 
			
		||||
            endMeasurements("goto_search");
 | 
			
		||||
 | 
			
		||||
            startMeasurements("search_video");
 | 
			
		||||
            UiObject textField = getUiObjectByResourceId(packageID + "search_edit_text");
 | 
			
		||||
            textField.setText(searchTerm);
 | 
			
		||||
            endMeasurements("search_video");
 | 
			
		||||
 | 
			
		||||
            getUiDevice().pressEnter();
 | 
			
		||||
            startMeasurements("play_from_search");
 | 
			
		||||
            // If a video exists whose title contains the exact search term, then play it
 | 
			
		||||
            // Otherwise click the first video in the search results
 | 
			
		||||
            UiObject thumbnail = new UiObject(new UiSelector().resourceId(packageID + "thumbnail"));
 | 
			
		||||
            UiObject matchedVideo = thumbnail.getFromParent(new UiSelector().textContains(searchTerm));
 | 
			
		||||
            if (matchedVideo.exists()) {
 | 
			
		||||
                matchedVideo.clickAndWaitForNewWindow();
 | 
			
		||||
            } else {
 | 
			
		||||
                thumbnail.clickAndWaitForNewWindow();
 | 
			
		||||
            }
 | 
			
		||||
            endMeasurements("play_from_search");
 | 
			
		||||
 | 
			
		||||
        } else if (SOURCE_TRENDING.equalsIgnoreCase(source)) {
 | 
			
		||||
            startMeasurements("goto_trending");
 | 
			
		||||
            clickUiObject(BY_DESC, "Trending");
 | 
			
		||||
            endMeasurements("goto_trending");
 | 
			
		||||
 | 
			
		||||
            startMeasurements("play_from_trending");
 | 
			
		||||
            clickUiObject(BY_ID, packageID + "thumbnail", true);
 | 
			
		||||
            endMeasurements("play_from_trending");
 | 
			
		||||
 | 
			
		||||
        } else { // homepage videos
 | 
			
		||||
            UiScrollable list = new UiScrollable(new UiSelector().resourceId(packageID + "results"));
 | 
			
		||||
            if (list.exists()) {
 | 
			
		||||
                list.scrollForward();
 | 
			
		||||
            }
 | 
			
		||||
            startMeasurements("play_from_home");
 | 
			
		||||
            clickUiObject(BY_ID, packageID + "thumbnail", true);
 | 
			
		||||
            endMeasurements("play_from_home");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        dismissAdvert();
 | 
			
		||||
        checkPlayerError();
 | 
			
		||||
        pausePlayVideo();
 | 
			
		||||
        checkVideoInfo();
 | 
			
		||||
        scrollRelated();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void dismissAdvert() throws Exception {
 | 
			
		||||
        UiObject advert = new UiObject(new UiSelector().textContains("Visit advertiser"));
 | 
			
		||||
        if (advert.exists()) {
 | 
			
		||||
            UiObject skip = new UiObject(new UiSelector().textContains("Skip ad"));
 | 
			
		||||
            if (skip.waitForExists(WAIT_TIMEOUT_5SEC)) {
 | 
			
		||||
                skip.click();
 | 
			
		||||
                sleep(VIDEO_SLEEP_SECONDS);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void checkPlayerError() throws Exception {
 | 
			
		||||
        UiObject playerError = new UiObject(new UiSelector().resourceId(packageID + "player_error_view"));
 | 
			
		||||
        UiObject tapToRetry = new UiObject(new UiSelector().textContains("Tap to retry"));
 | 
			
		||||
        if (playerError.waitForExists(WAIT_TIMEOUT_1SEC) || tapToRetry.waitForExists(WAIT_TIMEOUT_1SEC)) {
 | 
			
		||||
            throw new RuntimeException("Video player encountered an error and cannot continue.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void pausePlayVideo() throws Exception {
 | 
			
		||||
        UiObject player = getUiObjectByResourceId(packageID + "player_fragment_container");
 | 
			
		||||
        sleep(VIDEO_SLEEP_SECONDS);
 | 
			
		||||
        repeatClickUiObject(player, 2, 100);
 | 
			
		||||
        sleep(1); // pause the video momentarily
 | 
			
		||||
        player.click();
 | 
			
		||||
        startMeasurements("player_video_windowed");
 | 
			
		||||
        sleep(VIDEO_SLEEP_SECONDS);
 | 
			
		||||
        endMeasurements("player_video_windowed");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void checkVideoInfo() throws Exception {
 | 
			
		||||
        UiObject expandButton = new UiObject(new UiSelector().resourceId(packageID + "expand_button"));
 | 
			
		||||
        if (!expandButton.waitForExists(WAIT_TIMEOUT_1SEC)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // Expand video info
 | 
			
		||||
        expandButton.click();
 | 
			
		||||
        SystemClock.sleep(500); // short delay to simulate user action
 | 
			
		||||
        expandButton.click();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void scrollRelated() throws Exception {
 | 
			
		||||
        // ListView of related videos and (maybe) comments
 | 
			
		||||
        UiScrollable list = new UiScrollable(new UiSelector().resourceId(packageID + "watch_list"));
 | 
			
		||||
        if (list.isScrollable()) {
 | 
			
		||||
            startMeasurements("watch_list_fling_down");
 | 
			
		||||
            list.flingToEnd(LIST_SWIPE_COUNT);
 | 
			
		||||
            endMeasurements("watch_list_fling_down");
 | 
			
		||||
 | 
			
		||||
            startMeasurements("watch_list_fling_up");
 | 
			
		||||
            list.flingToBeginning(LIST_SWIPE_COUNT);
 | 
			
		||||
            endMeasurements("watch_list_fling_up");
 | 
			
		||||
        }
 | 
			
		||||
        // After flinging, give the window enough time to settle down before
 | 
			
		||||
        // the next step, or else UiAutomator fails to find views in time
 | 
			
		||||
        sleep(VIDEO_SLEEP_SECONDS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void startMeasurements(String testTag) throws Exception {
 | 
			
		||||
        logger = new ActionLogger(testTag, parameters);
 | 
			
		||||
        logger.start();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void endMeasurements(String testTag) throws Exception {
 | 
			
		||||
        logger.stop();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user