除了针对 Android 应用程序中的组件(诸如:Activty,Service,content provider)进行单元测试以外,在运行时对其用户接口(UI)的行为进行测试也很重要。UI 测似确保应用程序有正确的的 UI 输出来响应用户一系列的操做,好比一个按键输入或者按工具条,菜单,对话框,图片和其它 UI 操做。html
功能测试或者黑盒 UI 测试并不须要测试人员知道应用的内部实现细节,只需知道当用户执行某些操做或者进行某种输入时的输出便可。这种方法有利于分离团队中测试人员和开发人员的职责。java
普通的 UI 测试方法就是手工运行测试并验证应用程序的行为是否符合预期。可是这种方法既沉闷又耗时还容易出现偏差。更高效更可靠的方法是用测试框架软件进行 UI 自动化测试。自动化测试建立代码来执行测试任务(test case),测试任务覆盖各类使用场景,这样测试框架就能够以一种可重复的方式自动运行这些 test case。android
Overview程序员
Android SDK 提供了下面两个工具,来对你的应用程序进行自动化功能测试:shell
使用这两个工具必须安装下面两个版本的 Android 开发工具:app
Workflow for the the uiautomator testing framework框架
Analyzing Your Application’s UIide
在开始写 test case 以前,这有助于咱们熟悉待测应用的 UI 组件(包括 View 和控制)。对于链接开发电脑上的任何 Android 设备,咱们能够用 uiautomatorviewer 工具对其前台 UI 进行截屏。该工具提供一个方便的可视化界面,用于查看其布局层次以及 View 的属性。利用这些信息,咱们接下来就能够建立 uiautomator 测试代码了。函数
对待测应用程序的 UI 组件进行分析:工具
1.链接 Android 设备和开发电脑。
2.打开命令行窗口并到 <android-sdk>/tools/ 目录下
3.用下面命令运行该工具:
$ uiautomatorviewer
4.点击 uiautomatorviewer 图形界面上的 Device Screenshot 按钮截屏用于分析。
注意:若是你的电脑上连了多个设备,能够经过设置 ANDROID_SERIAL 环境变量来区分它们:
a.用下面命令查看链接设备的 serial numbers:
$ adb devices
b.经过设置 ANDROID_SEIAL 来选择一个设备用于测试:
Windows:
set ANDROID_SERIAL=<device serial number>
UNIX:
export ANDROID_SERIAL=<device serial number>
若是你只连了一个设备就不须要设置该值。
5.查看应用程序总 UI 属性:
Preparing to Test
在开始使用 uiautomator 测试框架以前,须要完成下面的准备工做:
Load the application to a device
若是你正在阅读该文档,极可能待测 Android 应用程序还没有发布。若是你有 apk 文件的拷贝,就能够经过 adb 工具把它安装到测试设备上去,如何用 adb 工具安装 APK 文件,请参考 adb 文档。
Identify the application’s UI components
在写 uiatomator 测试以前,首先要识别待测应用程序的 UI 组件。一般优秀应用的 UI 组件是可见的而且能够和用户交互的。UI 组件应该有可见的 text 标签或者 android:contentDescription 属性,或者二者兼具。
咱们能够用 uiautomatorviewer 工具方便地查看待测应用中可见的屏幕对象(UI 组件)。至于如何经过该工具来分析一个应用程序的屏幕信息,请参考 Analyzing Your Application’s UI 部分。关于 Android 提供了那些经常使用的 UI 组件,请参考 User Interface。
Ensure that the application is accessible
这一步,是由于 uiautomator 工具运行你的 UI 功能测试代码依赖于 Android 框架支持辅助功能的特性。要使用 uiautomator 工具,至少应该知足一下条件:
android:hint
attribute with any graphical icons used by controls that provide feedback to the user (for example, status or state information).关于实现、测试可访问性的更多信息,请参考 Making Applications Accessible。
通常状况下,经由 View 和 ViewGroup 类,Android 程序员能够轻易对辅助功能进行支持。可是有些应用使用自定义 view 组件以提供更好的用户体验。而这些自定义组件并无从标注 的 Android UI 组件那里继承到对辅助功能的支持。若是你的应用程序属于这种状况,请经过实现 AccessibilityNodeProvider 类来确保 Android 的辅助服务能够访问自定义 UI 组件。关于如何使自定义控件支持辅助功能,请参考 Making Applications Accessible。
Configure your development environment
若是你用 Eclipse 作开发,Android SDK 另外提供了工具来帮助你编写 uiautomator test case 并打包 jar 文件。要设置 Eclipse 以使用这些工具,须要建立一个包含 uiautomator 客户端库的工程,该库通常和 Android SDK 库在一块儿。配置 Eclipse:
a. 点击 Add Library > JUit,而后选择 JUnit3。
b. 点击 Add External JARs… 进入 SDK 目录,在 platforms 目录下,选择最新版本的 SDK目录,并选择 uiautomator.jar 和 android.jar 文件。
若是你不使用 Eclipse 作开发环境,请确保你的 Java class path 包括了 <android-sdk>/platforms/<sdk> 目录下的 uiautomator.jar 和 android.jar 文件。
这些准备工做完成后,立刻就能够建立 uiautomator 测试了。
Creating uiautomator Tests
要构建一个能够在 uiautomator 框架中运行的测试,首选要建立一个继承自 UiAutomatorTestCase 的类。在 Eclipse 中这个 test case 文件属于工程的 src 目录。而后,会把这个 test case 构建成一个 JAR 文件,最后把这个 JAR 文件复制到测试设备中。这个 JAR 文件并非一个 APK 文件,而且和待测应用是分离的。
由于 UiAutomatorTestCase 类继承自 junit.framework.TestCase,因此你能够用 JUnit 的 Assert 类来测试待测应用中的 UI 组件,看是否返回指望结果。要学习更多的 JUnit 知识,你能够阅读 junit.org 主页中的文档。
test case 的首要任务是将要访问安装了待测应用程序的设备。先对设备的 Home screen 作测试来练练手也是一个不错的选择。对于 Home Screen(或者待测应用的其它位置),你能够用 uiautomator 提供的 API 来模拟用户的操做对特定的 UI 组件进行测试。至于如何组织一个 uiautomator test case 请看 sample test case 部分。
uiautomator API
uiautomator API 在 <android-sdk>/platforms/ uiautomator.jar 文件中,该 API 中包含如下几个关键类,经过这些类咱们能够捕获、操做待测应用中的 UI 组件:
UiDevice
表明了设备的状态。在测试代码中,能够调用 UiDevice 实例中的函数来检测设备的各类属性状态,例如当前的屏幕的方向或者尺寸。也能够经过 UiDevice 实例来执行设备层次的操做,好比强制改变设备的方向,按下 d-pad 物理按键或者 Home 建和菜单按钮。
下面代码就是获取 UiDevice 实例,而后按下 Home 键:
getUiDevice().pressHome();
UiSelector
表示一个在当前显示界面查询、获取特定组件的搜素条件。若是找到多个匹配组件,那么就返回布局层次中的第一个匹配组件,返回的是一个 UIObject 对象。构造一个 UiSelector 对象时,能够组合多个属性使搜索更精确。若是一个也没找到,就会抛出一个 UiAutomatorObjectNotFoundException 异常。也能够用 childSelector() 函数来嵌套多个 UiSelector 实例。例如,下面的示例代码就展现了如何设定一个搜索条件,在当前显示界面中找到第一个 ListView,而后在这个 ListView 中搜索一个 text 属性为 “Apps”的 UI 组件。
UiObject appItem = new UiObject(new UiSelector() .className("android.widget.ListView").instance(1) .childSelector(new UiSelector().text("Apps")));
UiObject
表明一个 UI 组件。建立 一个 UiObject 实例时经过一个 UiSelector 对象来搜索对应的 UI 组件。
下面的示例代码展现了如何建立 UiObject 对象,这两个对象表示应用程序中的一个 Cancel 按钮和一个 OK 按钮。
UiObject cancelButton = new UiObject(new UiSelector().text("Cancel")); UiObject okButton = new UiObject(new UiSelector().text("OK"));
若是须要,你能够在测试程序的其它地方重用已经建立的 UiObject 实例。要注意的是,在测试代码中你每次用一个 UiObject 实例对一个 UI 组件进行点击操做或者查询其属性,uiautomator 测试框架都会在当前显示界面进行一次搜索。
在下面的示例代码中,uiautomator 测试框架会先搜索 text 属性为 “OK”的 UI 组件,若是存在而且是 enable 的,那么测试框架就会模拟用户对该组件进行点击操做。
if(okButton.exists() && okButton.isEnabled()) { okButton.click(); }
也能够限制搜索条件只搜索特定类的组件。例如,搜索 Button 类的组件:
UiObject cancelButton = new UiObject(new UiSelector().text("Cancel") .className("android.widget.Button")); UiObject okButton = new UiObject(new UiSelector().text("OK") .className("android.widget.Button"));
UiCollection
表明组件的集合,例如一个视频专辑或者收件箱。实例化 UiCollection 和实例化 UiObject 相似都要传一个 UiSelector 进去。对于 UiCollection,UiSelector 用于搜索多个子控件的容器(例如:一个包含子控件的 Layout)。例如,下面的代码片断展现了如何建立一个表明一个视频专辑的 UiCollection,该专辑显示在一个 FrameLayout 中:
UiCollection videos = new UiCollection(new UiSelector() .className("android.widget.FrameLayout"));
若是这些视频都显示在一个 LinearLayout 中,你又想获取这些视频的个数:
int count = videos.getChildCount(new UiSelector() .className("android.widget.LinearLayout"));
若是你要从中找出一个 text 属性为 “Cute Baby Laughting”的视频,并模拟用户去点击它:
UiObject video = videos.getChildByText(new UiSelector() .className("android.widget.LinearLayout"), "Cute Baby Laughing"); video.click();
对于这个 UI 对象上你一样能够模拟其它的用户操做。例如,你能够模拟选择一个与某一视频线关联的 checkbox:
UiObject checkBox = video.getChild(new UiSelector() .className("android.widget.Checkbox")); if(!checkBox.isSelected()) checkbox.click();
UiScollable
表明一个可滚动的 UI 组件集合。你能够用 UiScrollable 来模拟 UI 组件的垂直或者水平滚动。当一个 UI 组件显示在屏幕之外,你须要滚动才能看到它,这时候这个技术就颇有用。
例以下面的示例代码演示如何模拟向下滚动设置菜单并点击一个 About tablet 的选项:
UiScrollable settingsItem = new UiScrollable(new UiSelector() .className("android.widget.ListView")); UiObject about = settingsItem.getChildByText(new UiSelector() .className("android.widget.LinearLayout"), "About tablet"); about.click()
关于这些 API 的更多信息请参考 uiautomator。
A sample uiautomator test case
下面的示例代码是一个简单的 test case,它模拟用户在一个通用 Android 设备上进行设置应用程序的操做。该 test case 模拟用户执行这个任务一般会作的全部操做,包括打开 Home Screen,打开 All Apps Screen,滚动找到 Settings app 的图标,而后点击这个图标进入设置界面。
package com.uia.example.my; // Import the uiautomator libraries
import com.android.uiautomator.core.UiObject; import com.android.uiautomator.core.UiObjectNotFoundException; import com.android.uiautomator.core.UiScrollable; import com.android.uiautomator.core.UiSelector; import com.android.uiautomator.testrunner.UiAutomatorTestCase; public class LaunchSettings extends UiAutomatorTestCase { public void testDemo() throws UiObjectNotFoundException { // 模拟点击 HOME 按钮.
getUiDevice().pressHome(); // 如今在 Home Sceen. 接下来咱们模拟用户进入 All Apps 屏 // 若是用 uiautomatorviewer 工具对 Home Screen 进行截图分析// 就会发现 All Apps 按钮的 content-description 属性的值是 “Apps” // 咱们能够用这个属性值建立一个 UiSelector 来找到这个按钮。
UiObject allAppsButton = new UiObject(new UiSelector() .description("Apps")); // 模拟进入 All Apps 屏
allAppsButton.clickAndWaitForNewWindow(); // 设置按钮在 All Apps 屏的 “Apps tab” 中。咱们建立一个 UiSelector 找到 // text 属性是 “Apps” 的 tab ,而后模拟用户点击进入 Apps tab。
UiObject appsTab = new UiObject(new UiSelector() .text("Apps")); // 模拟点击进入 Apps tab
appsTab.click(); // 接下来在 Apps tab 中模拟用户滑动屏幕找到设置程序的图标。 // 由于这个 Apps tab 是能够滑动的,因此咱们能够用一个 UiScrollable 对象。
UiScrollable appViews = new UiScrollable(new UiSelector() .scrollable(true)); // 设置为水平滑动模式(模式是垂直滑动)
appViews.setAsHorizontalList(); // 建立一个 UiSelector 找到设置按钮, // 而后模拟用户点击加载这个程序
UiObject settingsApp = appViews.getChildByText(new UiSelector() .className(android.widget.TextView.class.getName()), "Settings"); settingsApp.clickAndWaitForNewWindow(); // 验证它的 package name 是否符合预期。
UiObject settingsValidation = new UiObject(new UiSelector() .packageName("com.android.settings")); assertTrue("Unable to detect Settings", settingsValidation.exists()); } }
Building and Deploying Your uiautomator Tests
完成测试代码以后,根据下面步骤来 build 并把 JAR 文件部署到测试机上:
<android-sdk>/tools/android create uitest-project -n <name> -t 1 -p <path>
<name> 是包含 uiautomator 测试源代码的工程名字,<path> 是项目文件夹的路径。
Windows:
set ANDROID_HOME=<path_to_your_sdk>
UNIX:
export ANDROID_HOME=<path_to_your_sdk>
ant build
下面是一个例子adb push <path_to_output_jar> /data/local/tmp/
adb push ~/dev/workspace/LaunchSettings/bin/LaunchSettings.jar /data/local/tmp/
Running uiautomator Tests
下面的例子是展现如何运行 LaunchSettings.jar 测试代码。该测试位于 com.uia.example.my 包中:
adb shell uiautomator runtest LaunchSettings.jar -c com.uia.example.my.LaunchSettings
关于 uiautomator 的语法、命令、设置的详细信息请参考 uiautomator。
Best Practices
下面是一些用 uiautomator 框架进行 UI 功能测试的最佳实践: