mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-01-18 20:11:20 +00:00
Multiapp Workload: Workload to test how responsive a device is when context switching between appplication tasks. It combines workflows from googlephotos, gmail and skype.
Added tagName to give unique logger name for multiple share attempts. Turn off markers_enabled for subclasses Renamed multiapp to appshare. Description is now more accurate Changed appshare to use class instances for each sub workload. This allows APKs to be setup correctly on the device Photos changed function name
This commit is contained in:
parent
b1e375a676
commit
51f07c4473
183
wlauto/workloads/appshare/__init__.py
Executable file
183
wlauto/workloads/appshare/__init__.py
Executable file
@ -0,0 +1,183 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
import os
|
||||
|
||||
from wlauto import AndroidUxPerfWorkload, Parameter, ExtensionLoader
|
||||
from wlauto import AndroidUiAutoBenchmark, UiAutomatorWorkload
|
||||
from wlauto.exceptions import ValidationError
|
||||
|
||||
|
||||
class AppShare(AndroidUxPerfWorkload):
|
||||
|
||||
name = 'appshare'
|
||||
package = []
|
||||
activity = None
|
||||
view = []
|
||||
description = '''
|
||||
Workload to test how responsive a device is when context switching between
|
||||
application tasks. It combines workflows from googlephotos, gmail and
|
||||
skype.
|
||||
|
||||
** Setup **
|
||||
Credentials for the user account used to log into the Skype app have to be provided
|
||||
in the agenda, as well as the display name of the contact to call.
|
||||
|
||||
For reliable testing, this workload requires a good and stable internet connection,
|
||||
preferably on Wi-Fi.
|
||||
|
||||
Although this workload attempts to be network independent it requires a
|
||||
network connection (ideally, wifi) to run. This is because the welcome
|
||||
screen UI is dependent on an existing connection.
|
||||
|
||||
Test description:
|
||||
1. GooglePhotos is started in offline access mode
|
||||
1.1. The welcome screen is dismissed
|
||||
1.2. Any promotion popup is dismissed
|
||||
1.3. The provided ``test_image`` is selected and displayed
|
||||
2. The image is then shared across apps to Gmail
|
||||
2.1. The first run dialogue is dismissed
|
||||
2.2. Enter recipient details in the To field
|
||||
2.3. Enter text in the Subject field
|
||||
2.4. Enter text in the Body field
|
||||
2.5. Click the Send mail button
|
||||
3. Return to Googlephotos and login to Skype via share action
|
||||
4. Return to Googlephotos and share the ``test_image`` with Skype
|
||||
4.1. Search for the ``skype_contact_name`` from the Contacts list
|
||||
4.2. Dismiss any update popup that appears
|
||||
4.3. The image is posted in the Chat
|
||||
'''
|
||||
|
||||
parameters = [
|
||||
Parameter('test_image', kind=str, default='uxperf_1600x1200.jpg',
|
||||
description='''
|
||||
An image to be copied onto the device that will be shared
|
||||
across multiple apps
|
||||
'''),
|
||||
Parameter('email_recipient', kind=str, default='wa-devnull@mailinator.com',
|
||||
description='''
|
||||
The email address of the recipient to recieve the shared image
|
||||
'''),
|
||||
Parameter('skype_login_name', kind=str, mandatory=True,
|
||||
description='''
|
||||
Account to use when logging into skype from which to share the image
|
||||
'''),
|
||||
Parameter('skype_login_pass', kind=str, mandatory=True,
|
||||
description='''
|
||||
Password associated with the skype account
|
||||
'''),
|
||||
Parameter('skype_contact_name', kind=str, default='Echo / Sound Test Service',
|
||||
description='''
|
||||
This is the contact display name as it appears in the people list
|
||||
'''),
|
||||
]
|
||||
|
||||
# This workload relies on the internet so check that there is a working
|
||||
# internet connection
|
||||
requires_network = True
|
||||
|
||||
def __init__(self, device, **kwargs):
|
||||
super(AppShare, self).__init__(device, **kwargs)
|
||||
self.deployable_assets = [self.test_image]
|
||||
self.clean_assets = True
|
||||
loader = ExtensionLoader()
|
||||
|
||||
# Initialise googlephotos
|
||||
args_googlephotos = dict(kwargs)
|
||||
del args_googlephotos['test_image']
|
||||
del args_googlephotos['email_recipient']
|
||||
del args_googlephotos['skype_login_name']
|
||||
del args_googlephotos['skype_login_pass']
|
||||
del args_googlephotos['skype_contact_name']
|
||||
args_googlephotos['markers_enabled'] = False
|
||||
self.wl_googlephotos = loader.get_workload('googlephotos', device, **args_googlephotos)
|
||||
self.view += self.wl_googlephotos.view
|
||||
self.package.append(self.wl_googlephotos.package)
|
||||
|
||||
# Initialise gmail
|
||||
args_gmail = dict(kwargs)
|
||||
del args_gmail['test_image']
|
||||
args_gmail['recipient'] = args_gmail.pop('email_recipient')
|
||||
del args_gmail['skype_login_name']
|
||||
del args_gmail['skype_login_pass']
|
||||
del args_gmail['skype_contact_name']
|
||||
args_gmail['markers_enabled'] = False
|
||||
self.wl_gmail = loader.get_workload('gmail', device, **args_gmail)
|
||||
self.view += self.wl_gmail.view
|
||||
self.package.append(self.wl_gmail.package)
|
||||
|
||||
# Initialise skype
|
||||
args_skype = dict(kwargs)
|
||||
del args_skype['test_image']
|
||||
del args_skype['email_recipient']
|
||||
args_skype['login_name'] = args_skype.pop('skype_login_name')
|
||||
args_skype['login_pass'] = args_skype.pop('skype_login_pass')
|
||||
args_skype['contact_name'] = args_skype.pop('skype_contact_name')
|
||||
args_skype['markers_enabled'] = False
|
||||
self.wl_skype = loader.get_workload('skype', device, **args_skype)
|
||||
self.view += self.wl_skype.view
|
||||
self.package.append(self.wl_skype.package)
|
||||
|
||||
def validate(self):
|
||||
super(AppShare, self).validate()
|
||||
# Set package to None as it doesnt allow it to be a list,
|
||||
# and we are not using it in the java side, only in wa itself.
|
||||
self.uiauto_params['package'] = None
|
||||
self.uiauto_params['googlephotos_package'] = self.wl_googlephotos.package
|
||||
self.uiauto_params['gmail_package'] = self.wl_gmail.package
|
||||
self.uiauto_params['skype_package'] = self.wl_skype.package
|
||||
self.uiauto_params['recipient'] = self.email_recipient
|
||||
self.uiauto_params['my_id'] = self.skype_login_name
|
||||
self.uiauto_params['my_pwd'] = self.skype_login_pass
|
||||
self.uiauto_params['name'] = self.skype_contact_name.replace(' ', '0space0')
|
||||
# Only accept certain image formats
|
||||
if os.path.splitext(self.test_image.lower())[1] not in ['.jpg', '.jpeg', '.png']:
|
||||
raise ValidationError('{} must be a JPEG or PNG file'.format(self.test_image))
|
||||
|
||||
def setup(self, context):
|
||||
self.logger.info('Checking dependency Skype')
|
||||
self.wl_skype.launch_main = False
|
||||
self.wl_skype.deployable_assets = []
|
||||
self.wl_skype.init_resources(context)
|
||||
# Bypass running skype through intent
|
||||
AndroidUxPerfWorkload.setup(self.wl_skype, context)
|
||||
|
||||
self.logger.info('Checking dependency Gmail')
|
||||
self.wl_gmail.launch_main = False
|
||||
self.wl_gmail.deployable_assets = []
|
||||
self.wl_gmail.init_resources(context)
|
||||
self.wl_gmail.setup(context)
|
||||
|
||||
self.logger.info('Checking dependency Googlephotos')
|
||||
self.wl_googlephotos.launch_main = True
|
||||
self.wl_googlephotos.deployable_assets = []
|
||||
self.wl_googlephotos.init_resources(context)
|
||||
# Bypass googlephoto's asset setup
|
||||
AndroidUxPerfWorkload.setup(self.wl_googlephotos, context)
|
||||
|
||||
self.logger.info('Checking dependency AppShare')
|
||||
super(AppShare, self).init_resources(context)
|
||||
# Only setup uiautomator side, then push assets
|
||||
# This prevents the requirement that AppShare must have an APK
|
||||
UiAutomatorWorkload.setup(self, context)
|
||||
self.push_assets(context)
|
||||
|
||||
def teardown(self, context):
|
||||
self.wl_skype.teardown(context)
|
||||
self.wl_gmail.teardown(context)
|
||||
# Bypass googlephoto's asset teardown
|
||||
AndroidUxPerfWorkload.teardown(self.wl_googlephotos, context)
|
||||
|
||||
super(AppShare, self).teardown(context)
|
BIN
wlauto/workloads/appshare/com.arm.wlauto.uiauto.appshare.jar
Normal file
BIN
wlauto/workloads/appshare/com.arm.wlauto.uiauto.appshare.jar
Normal file
Binary file not shown.
49
wlauto/workloads/appshare/uiauto/build.sh
Executable file
49
wlauto/workloads/appshare/uiauto/build.sh
Executable file
@ -0,0 +1,49 @@
|
||||
#!/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
|
||||
|
||||
# Add appshare workload dependencies
|
||||
apps=("googlephotos" "gmail" "skype")
|
||||
|
||||
for app in "${apps[@]}"; do
|
||||
module_path="wlauto.workloads.${app}"
|
||||
app_path="'uiauto/bin/classes/com/arm/wlauto/uiauto/${app}'"
|
||||
app_class_dir=`python -c "import os, ${module_path}; print os.path.join(os.path.dirname(${module_path}.__file__), ${app_path})"`
|
||||
cp -r $app_class_dir $class_dir
|
||||
done
|
||||
|
||||
# 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.appshare.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/appshare/uiauto/build.xml
Normal file
92
wlauto/workloads/appshare/uiauto/build.xml
Normal file
@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="com.arm.wlauto.uiauto.appshare" 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/appshare/uiauto/project.properties
Normal file
14
wlauto/workloads/appshare/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
|
143
wlauto/workloads/appshare/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java
Executable file
143
wlauto/workloads/appshare/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java
Executable file
@ -0,0 +1,143 @@
|
||||
package com.arm.wlauto.uiauto.appshare;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
// 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;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class UiAutomation extends UxPerfUiAutomation {
|
||||
|
||||
// Create UIAutomation objects
|
||||
private com.arm.wlauto.uiauto.googlephotos.UiAutomation googlephotos =
|
||||
new com.arm.wlauto.uiauto.googlephotos.UiAutomation();
|
||||
|
||||
private com.arm.wlauto.uiauto.gmail.UiAutomation gmail =
|
||||
new com.arm.wlauto.uiauto.gmail.UiAutomation();
|
||||
|
||||
private com.arm.wlauto.uiauto.skype.UiAutomation skype =
|
||||
new com.arm.wlauto.uiauto.skype.UiAutomation();
|
||||
|
||||
public Bundle parameters;
|
||||
|
||||
public void runUiAutomation() throws Exception {
|
||||
// Override superclass value
|
||||
this.uiAutoTimeout = TimeUnit.SECONDS.toMillis(10);
|
||||
|
||||
parameters = getParams();
|
||||
|
||||
// Setup the three uiautomator classes with the correct information
|
||||
// Also create a dummy parameter to disable marker api as they
|
||||
// should not log actions themselves.
|
||||
Bundle dummyParams = new Bundle();
|
||||
dummyParams.putString("markers_enabled", "false");
|
||||
googlephotos.parameters = dummyParams;
|
||||
googlephotos.packageName = parameters.getString("googlephotos_package");
|
||||
googlephotos.packageID = googlephotos.packageName + ":id/";
|
||||
gmail.parameters = dummyParams;
|
||||
gmail.packageName = parameters.getString("gmail_package");
|
||||
gmail.packageID = gmail.packageName + ":id/";
|
||||
skype.parameters = dummyParams;
|
||||
skype.packageName = parameters.getString("skype_package");
|
||||
skype.packageID = skype.packageName + ":id/";
|
||||
|
||||
String recipient = parameters.getString("recipient");
|
||||
String loginName = parameters.getString("my_id");
|
||||
String loginPass = parameters.getString("my_pwd");
|
||||
String contactName = parameters.getString("name").replace("0space0", " ");
|
||||
|
||||
setScreenOrientation(ScreenOrientation.NATURAL);
|
||||
|
||||
setupGooglePhotos();
|
||||
sendToGmail(recipient);
|
||||
logIntoSkype(loginName, loginPass);
|
||||
// Skype won't allow us to login and share on first visit so invoke
|
||||
// once more from googlephotos
|
||||
pressBack();
|
||||
pressBack();
|
||||
sendToSkype(contactName);
|
||||
|
||||
unsetScreenOrientation();
|
||||
}
|
||||
|
||||
private void setupGooglePhotos() throws Exception {
|
||||
googlephotos.dismissWelcomeView();
|
||||
googlephotos.closePromotionPopUp();
|
||||
selectGalleryFolder("wa-working");
|
||||
googlephotos.selectFirstImage();
|
||||
}
|
||||
|
||||
private void sendToGmail(String recipient) throws Exception {
|
||||
String gID = gmail.packageID;
|
||||
|
||||
shareUsingApp("Gmail", "gmail");
|
||||
|
||||
gmail.clearFirstRunDialogues();
|
||||
|
||||
UiObject composeView =
|
||||
new UiObject(new UiSelector().resourceId(gID + "compose"));
|
||||
if (!composeView.waitForExists(uiAutoTimeout)) {
|
||||
// After the initial share request on some devices Gmail returns back
|
||||
// to the launching app, so we need to share the photo once more and
|
||||
// wait for Gmail to sync.
|
||||
shareUsingApp("Gmail", "gmail_retry");
|
||||
|
||||
gmail.clearFirstRunDialogues();
|
||||
}
|
||||
|
||||
gmail.setToField(recipient);
|
||||
gmail.setSubjectField();
|
||||
gmail.setComposeField();
|
||||
gmail.clickSendButton();
|
||||
}
|
||||
|
||||
private void logIntoSkype(String loginName, String loginPass) throws Exception {
|
||||
shareUsingApp("Skype", "skype_setup");
|
||||
|
||||
skype.handleLoginScreen(loginName, loginPass);
|
||||
|
||||
sleep(10); // Pause while the app settles before returning
|
||||
}
|
||||
|
||||
private void sendToSkype(String contactName) throws Exception {
|
||||
shareUsingApp("Skype", "skype");
|
||||
|
||||
skype.searchForContact(contactName);
|
||||
skype.dismissUpdatePopupIfPresent();
|
||||
|
||||
sleep(10); // Pause while the app settles before returning
|
||||
}
|
||||
|
||||
private void shareUsingApp(String appName, String tagName) throws Exception {
|
||||
String testTag = "share";
|
||||
ActionLogger logger = new ActionLogger(testTag + "_" + tagName, parameters);
|
||||
|
||||
clickUiObject(BY_DESC, "Share", "android.widget.ImageView");
|
||||
UiScrollable applicationGrid =
|
||||
new UiScrollable(new UiSelector().resourceId(googlephotos.packageID + "application_grid"));
|
||||
UiObject openApp =
|
||||
new UiObject(new UiSelector().text(appName)
|
||||
.className("android.widget.TextView"));
|
||||
// On some devices the application_grid has many entries, se we have to swipe up to make
|
||||
// sure all the entries are visable. This will also stop entries at the bottom being
|
||||
// obscured by the bottom action bar.
|
||||
applicationGrid.swipeUp(10);
|
||||
while (!openApp.exists()) {
|
||||
// In the rare case the grid is larger than the screen swipe up
|
||||
applicationGrid.swipeUp(10);
|
||||
}
|
||||
|
||||
logger.start();
|
||||
openApp.clickAndWaitForNewWindow();
|
||||
logger.stop();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user