一、自动化测试的必要性
Android程序开发迭代周期短,测试case重复度高,大部分case属于功能验证,常规的测试方法是测试人员按照预先写好的Case手顺进行测试,人工比对操作结果和预期结果。这种测试手段重复度高,效率低,无趣,易出错,并且对测试人员能力提升帮助有限。Android手机机型狂多,屏幕尺寸各异,语言各异,因此测试重复度很高,完全依赖人力并不现实。同时自动化测试可以方便的整合入Jenkins等CI工具,可以覆盖掉相当部分的UI正确性检测。二、自动化测试工具介绍
Android发展至今,出现了许多自动化测试工具,许多实力派企业甚至开发了专用测试工具。常用的大致有以下几种: 1.Monkey:压力测试好伙伴 2.MonkeyRunner:支持录制功能,支持Python,但是API太弱,可以二次开发。 3.Appium:支持ios,支持的语言丰富,但许多语言API不完善。支持 跨平台 ,社区资源有限,环境搭建太复杂。4.Rubotium:功能强大,发展多年,社区资源丰富,使用略复杂。
5.Calabash:支持ios,功能强大,社区资源太少。 6.淘宝的TMTS:没用过,不评论。 7.UIAutomator:Android4.1同步推出,兼容JUnit,基本上可以替代所有第三方测试工具。有朋友反映第一次使用搭建环境略复杂。
三、为什么选择UiAutomator
作为亲儿子UiAutomator随Android同步推出,随Android版本同步升级,经过多次迭代目前已经相当稳定。 相比MonkeyRunner,UiAutomator接口丰富易用,可以支持所有Android事件操作,事件操作不依赖于控件坐标,可以通过断言和截图验证正确性,非常适合做UI测试。 UIAutomator不需要测试人员了解代码实现细节,属于功能和黑盒测试。测试代码结构简单,编写容易,学习曲线低。基于JAVA,一次编译可以运行于所有Android设备。注: UIAutomator不适合 OpenGL 和HTML为主的程序,因为这类程序未使用 Android 的view体系。
四、UIAutomator的使用准备
1.首先介绍UIAutomator测试框架的UI工具:uiautomatorviewer
uiautomatorviewer位于sdk/tools目录下,可以扫描、分析待测试应用界面,分析结果可以导出为xml与截图。通过该工具可以分析出UI控件的id,text,focusable等等各种属性,甚至布局上的层次关系。可以通过./uiautomatorviewer启动该工具。
上图uiautomatorviewer的运行截图,左上角两个手机模样的图标点击后就会开始截图并分析UI组件,分析后的结果如下方所示, 左侧为手机当前画面截图,右侧上部为view控件的层次关系,下部为当前选中控件的各种信息。例如当前选中了 "X"号,可以看到该控件是一个Button,属于一个LinearLayout,在LinearLayout中的index是3,text是X,id是mul,contentDescription是“乘”,可以点击,可以获得焦点等等。。。 相信看到这个大家起码已经觉得这个工具很牛X了,确实对于开发的同学该工具也会很有帮助。
2.现在介绍uiautomator
uiautomator是一个包含一套UI测试API,和支持运行测试程序的JAR包。该JAR包位于sdk/platforms/android-*/uiautomator.jar. 使用时需要注意自己的SDK版本需要大于16, SDK Tools版本需要大于21.五.uiautomator的使用步骤
下面用一个例子介绍uiautomator的使用。在该例子中我们将启动计算器程序并测试1+1的结果是否正确。 以Eclipse为例: 1.创建一个Java工程 File-->New-->Java Project 输入工程名称,例如CalculatorAutoTest. 点击Finish2.添加必要的Jar包 在Project Explorer中右击刚刚创建的这个工程,选择 Properties-->Java build Path添加如下JAR包 a.选择Add library -->JUnit选择Junit4 b.选择Add External JARS, 选择sdk/platforms/android-*/目录下的uiautomator.jar和android.jar,路径中的*请使用自己以下载的最新版本。
3.File-->new-->Class创建一个新的文件,并确保该文件继承自UiAutomatorTestCase.
1.
public
class
CalTest
extends
UiAutomatorTestCase {
2.
3.
}
4.编写测试用例,通常可以为一个测试用例编写一个单独的方法:
01.
package
xzy.test.uiautomator;
02.
03.
import
java.io.IOException;
04.
05.
import
android.os.RemoteException;
06.
07.
import
com.android.uiautomator.core.UiDevice;
08.
import
com.android.uiautomator.core.UiObject;
09.
import
com.android.uiautomator.core.UiObjectNotFoundException;
10.
import
com.android.uiautomator.core.UiSelector;
11.
import
com.android.uiautomator.testrunner.UiAutomatorTestCase;
12.
13.
public
class
CalTest
extends
UiAutomatorTestCase {
14.
15.
public
void
testDemo()
throws
UiObjectNotFoundException, RemoteException {
16.
17.
UiDevice device = getUiDevice();
18.
// 唤醒屏幕
19.
device.wakeUp();
20.
assertTrue(
"screenOn: can't wakeup"
, device.isScreenOn());
21.
// 回到HOME
22.
device.pressHome();
23.
sleep(
1000
);
24.
25.
// 启动计算器App
26.
try
{
27.
Runtime.getRuntime().exec(
28.
"am start -n com.android.calculator2/.Calculator"
);
29.
}
catch
(IOException e) {
30.
// TODO Auto-generated catch block
31.
e.printStackTrace();
32.
}
33.
34.
sleep(
1000
);
35.
UiObject oneButton =
new
UiObject(
new
UiSelector().text(
"1"
));
36.
assertTrue(
"oneButton not found"
, oneButton.exists());
37.
UiObject plusButton =
new
UiObject(
new
UiSelector().text(
"+"
));
38.
assertTrue(
"plusButton not found"
, plusButton.exists());
39.
40.
sleep(
100
);
41.
42.
UiObject equalButton =
new
UiObject(
new
UiSelector().text(
"="
));
43.
assertTrue(
"equalButton not found"
, equalButton.exists());
44.
45.
oneButton.click();
46.
sleep(
100
);
47.
plusButton.click();
48.
sleep(
100
);
49.
oneButton.click();
50.
51.
equalButton.click();
52.
sleep(
100
);
53.
54.
UiObject switcher =
new
UiObject(
55.
new
UiSelector()
56.
.resourceId(
"com.android.calculator2:id/display"
));
57.
UiObject result = switcher.getChild(
new
UiSelector().index(
0
));
58.
System.out.print(
"text is :"
+ result.getText());
59.
assertTrue(
"result != 2"
, result.getText().equals(
"2"
));
60.
}
61.
}
5.编译测试用例 uiautomator的编译工具是Ant,在编译之前我们先要生成build.xml,生成方法如下:
1.
<android-sdk>/tools/android create uitest-project -n <name> -t
3
-p <path>
其中<name>是包含uiautomator测试源文件的测试项目名称,<path> 是对应的测试项目目录的路径。 -t 后面的参数是android版本在当前sdk中的target值,通常一个sdk中我们会下载多个版本的android platform 可以通过一下命令查看:
1.
<android-sdk>/tools/android
输出如下:
01.
</pre><pre name=
"code"
class
=
"html"
>Available <a href=
"http://www.it165.net/pro/ydad/"
target=
"_blank"
class
=
"keylink"
>Android</a> targets:
02.
----------
03.
id:
1
or
"android-16"
04.
Name: Android
4.1
.
2
05.
Type: Platform
06.
API level:
16
07.
Revision:
4
08.
Skins: WQVGA400, WSVGA, WXGA800, HVGA, WVGA854, QVGA, WVGA800 (
default
), WQVGA432, WXGA720, WXGA800-7in
09.
Tag/ABIs :
default
/armeabi-v7a
10.
----------
11.
id:
2
or
"android-19"
12.
Name: Android
4.4
.
2
13.
Type: Platform
14.
API level:
19
15.
Revision:
3
16.
Skins: WQVGA400, WSVGA, WXGA800, HVGA, WVGA854, QVGA, WVGA800 (
default
), WQVGA432, WXGA720, WXGA800-7in
17.
Tag/ABIs :
default
/armeabi-v7a
18.
----------
19.
id:
3
or
"android-20"
20.
Name: Android
4
.4W
21.
Type: Platform
22.
API level:
20
23.
Revision:
1
24.
Skins: WQVGA400, WSVGA, WXGA800, HVGA, WVGA854, QVGA, WVGA800 (
default
), WQVGA432, WXGA720, WXGA800-7in, AndroidWearRound, AndroidWear Square, AndroidWearRound, AndroidWearSquare
25.
Tag/ABIs : android-wear/armeabi-v7a, android-wear/x86
这里应该和之前添加Library选择的一致,所以-t 后面我写的是3.
运行后输出如下:
1.
Added file /home/zhengyangxu/selfworkspace/CalculatorAutoTest/build.xml
到此,build.xml已经生成完毕,下面我们进入到工程目录下进行编译: 注:编译需要安装ant,安装方式请google之
1.
cd ~/selfworkspace/CalculatorAutoTest
2.
ant build
编译成功会输出如下信息:
01.
-post-dex:
02.
03.
-jar:
04.
[jar] Building jar: /home/zhengyangxu/selfworkspace/CalculatorAutoTest/bin/CalculatorAutoTest.jar
05.
06.
-post-jar:
07.
08.
build:
09.
10.
BUILD SUCCESSFUL
11.
Total time:
1
second
可见编译后的jar路径为:
1.
/home/zhengyangxu/selfworkspace/CalculatorAutoTest/bin/CalculatorAutoTest.jar
1.
adb push /home/zhengyangxu/selfworkspace/CalculatorAutoTest/bin/CalculatorAutoTest.jar /data/local/tmp/
最后运行jar文件:
1.
adb shell uiautomator runtest CalculatorAutoTest.jar -c xzy.test.uiautomator.CalTest
运行成功结果如下:
1.
Test results
for
WatcherResultPrinter=.
2.
Time:
6.793
3.
4.
OK (
1
test)
如果失败会出现类似以下信息:
01.
Failure in testDemo:
02.
junit.framework.AssertionFailedError: result !=
2
03.
at xzy.test.uiautomator.CalTest.testDemo(CalTest.java:
64
)
04.
at java.lang.reflect.Method.invokeNative(Native Method)
05.
at com.android.uiautomator.testrunner.UiAutomatorTestRunner.start(UiAutomatorTestRunner.java:
160
)
06.
at com.android.uiautomator.testrunner.UiAutomatorTestRunner.run(UiAutomatorTestRunner.java:
96
)
07.
at com.android.commands.uiautomator.RunTestCommand.run(RunTestCommand.java:
91
)
08.
at com.android.commands.uiautomator.Launcher.main(Launcher.java:
83
)
09.
at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
10.
at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:
243
)
11.
at dalvik.system.NativeStart.main(Native Method)
12.
13.
INSTRUMENTATION_STATUS: id=UiAutomatorTestRunner
14.
INSTRUMENTATION_STATUS: test=testDemo
15.
INSTRUMENTATION_STATUS:
class
=xzy.test.uiautomator.CalTest
16.
INSTRUMENTATION_STATUS: stack=junit.framework.AssertionFailedError: result !=
2
17.
at xzy.test.uiautomator.CalTest.testDemo(CalTest.java:
64
)
18.
at java.lang.reflect.Method.invokeNative(Native Method)
19.
at com.android.uiautomator.testrunner.UiAutomatorTestRunner.start(UiAutomatorTestRunner.java:
160
)
20.
at com.android.uiautomator.testrunner.UiAutomatorTestRunner.run(UiAutomatorTestRunner.java:
96
)
21.
at com.android.commands.uiautomator.RunTestCommand.run(RunTestCommand.java:
91
)
22.
at com.android.commands.uiautomator.Launcher.main(Launcher.java:
83
)
23.
at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
24.
at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:
243
)
25.
at dalvik.system.NativeStart.main(Native Method)
运行失败的话,根据提示信息解决一下就可以了。
至此,我们已经跑了一个简单的UIAutomator测试程序,下一篇中会介绍一些UIAutomator的使用技巧。
Demo源码下载:
1.
git
@github
.com:xzy2046/UIAutomatorDemo.git