Google大神镇楼 : http://developer.android.com/tools/testing-support-library/index.html#UIAutomator
前言: 觉得文章太长不想往后翻的朋友,你们会后悔的,当然,你也可以选择先看后面的,你会觉得很爽,但是相信我,你还是会回来看前面的。那么,还是慢慢往后翻吧。
导入: 人们懒的走路,才创造了汽车; 人们懒的爬楼,才创造了电梯; 人们懒的扫地,才创造了自动扫地机器人。 人类的进步,离不开这些喜欢偷懒的人,现在,程序猿将偷懒上升到了一个新的高度——利用程序来进行自动化软件测试,将测试工程师从繁琐的测试用例中解脱出来,从此可以一边喝着咖啡,一边看着程序自动测试,不必看着测试用例重复无数次的测试步骤,也不必担心操作失误而导致不必要的错误,更不用担心压力测试而导致的身心俱疲。想了解程序猿是如何实现自动化测试的吗,这里有你想要的答案。
声明 转载真的请注明出处: http://blog.csdn.net/eclipsexys
顺便打个广告: 我的慕课网视频: http://www.imooc.com/space/teacher/id/347333
——总而言之一句话——软件测试,决定着软件的质量。
以前在TCL的时候,每个软件版本都要不停的跑MonkeyTest,一个是检测系统ROM的稳定性,一个是检测各种第三方应用在ROM上的使用情况,所以经常会报出很多Monkey跑出来的Bug,这些Bug经过我们分析,会初步判断是第三方App的问题还是系统的ROM问题,如果是第三方的问题,我们也会提交给App的运营商,但是大部分的运营商给我们的回复都是,我们的App不支持跑Monkey,其实Monkey可以发现一些潜在的问题,特别是一些很难复现的问题,我以前的leader曾经说过一句话我觉得非常好,没有什么bug是不能复现的,没有复现,只是没有找到必先的步骤,所以每一个bug都不是偶然的,我们应该尽量严谨的分析每一个可能存在的bug。
再以前的时候,对日的公司对测试更是无比看重,各种UT测试式样书,不仅仅是要写好怎么测试、测试什么,而且测试的数据、中间过程还要截图,保留证据。
对于美国的手机运营商,例如T-Mobile、Sprite、AT&T,他们都有一系列的手机性能测试,他们的测试项目、测试方法、测试过程,其实都是他们的商业机密,一个是保证测试结果的严谨性,一个也保证了手机厂商能够不作弊的完成测试,所以,千万不要学华X手机,在T-Mobile实验室偷拍手机测试机器人的软件、技术参数及其他机密信息,而被T-Mobile列入北美黑名单。逗比新闻
自动化测试是把以人为驱动的测试行为转化为机器执行的一种过程
自动化测试的工具
各个测试框架的优缺点如下表所示:
测试框架 使用语言 运行方式 限制 适用环境 MonkeyRunner Python ADB、Python 测试靠坐标 压力测试 Instrumentation Java ADB 只能单个Activity测试,且需要应用相同签名,代码量大 白盒测试 Robotium 同上 同上 同上 同上 UiAutomator Java ADB或者脱机 Android 4.X+ UI测试综上所述,我们使用UiAutomator作为我们Android自动化测试的首选框架。
开发环境:eclipse(非常抱歉,还没学会如何使用AS来开发Java代码、进行jar打包,请了解的朋友留言!!!) 编译环境:Ant、Java、Android SDK
通常用于获取系统的设备信息、系统按键、全局操作等。
送个视频,让大家真实体验下:
视频代码:
1 <br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressBack();<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressBack();<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressHome();<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressMenu();<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressBack();<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressRecentApps();<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressHome();<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().click( 240 , 1100 );<br /><%%KEEPWHITESPACE%%> sleep( 2000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().click( 670 , 1100 );<br /><%%KEEPWHITESPACE%%> sleep( 2000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressKeyCode(KeyEvent.KEYCODE_H);<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressKeyCode(KeyEvent.KEYCODE_H, 1 );<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressKeyCode(KeyEvent.KEYCODE_J);<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressKeyCode(KeyEvent.KEYCODE_J, 1 );<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().swipe( 30 , 400 , 600 , 400 , 10 );<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressHome();<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().drag( 660 , 860 , 360 , 360 , 50 );<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().sleep();<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().wakeUp();<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().swipe( 370 , 1000 , 370 , 200 , 50 );<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().takeScreenshot( new File( "/sdcard/uidevice.png" ));<br />通常使用UiSelector,通过各种属性节点和关系来定位组件,类似SQL语句的where条件。
要查看界面UI元素的层级关系,我们需要使用SDK/tools/下面的uiautomatorviewer工具来帮助我们进行查看,运行uiautomatorviewer,点击dump,我们就可以获取当前界面的UI快照。 下面这张图就是一个示例:
通过uiautomatorviewer,我们可以找到很多对象的属性,上图右下角的方框中的,都是对象所具有的属性。我们可以通过这些属性来定位需要的元素对象,这里要注意的是,uiautomator可以使用链式查找,即一个条件无法定位,那么可以通过多个条件组合,来定位一个元素。
这种方式适用于当前页面上只有一种类型的组件的情况,例如只有一个ListView。
返回值方法解释UiSelectorclassName(className)通过class定位UiSelectorclassNameMatches(regex)通过class正则定位UiSelectorpackageName(name)通过package定位UiSelectorpackageNameMatches(regex)通过package正则定位对象的所有属性都可以使用,这里不再列举。
UIObject是UiAutomator的核心属性之一。它代表了整个UI界面中的所有对象元素。 它的功能包括:获取UI元素,点击、拖拽、滑动、对象属性判断、手势等。
还有很多,不列举了。
还有很多,不列举了。
再送一个视频、不收费:
视频代码:
1 <br /><%%KEEPWHITESPACE%%> UiObject word = new UiObject( new UiSelector().text( "沪江开心词场" ));<br /><%%KEEPWHITESPACE%%> word.clickAndWaitForNewWindow();<br /><%%KEEPWHITESPACE%%> UiObject username = new UiObject( new UiSelector().text( "沪江用户名/邮箱/手机" ));<br /><%%KEEPWHITESPACE%%> username.setText( "xuyisheng" );<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiObject pwd = new UiObject(<br /><%%KEEPWHITESPACE%%> new UiSelector().resourceId( "com.hjwordgames:id/edit_password" ));<br /><%%KEEPWHITESPACE%%> pwd.setText( "123465" );<br /><%%KEEPWHITESPACE%%> sleep( 2000 );<br /><%%KEEPWHITESPACE%%> pwd.clearTextField();<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> pwd.setText( "123465" );<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressBack();<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiObject login = new UiObject( new UiSelector().text( "登 录" ));<br /><%%KEEPWHITESPACE%%> login.clickAndWaitForNewWindow();<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressBack();<br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressBack();<br /><%%KEEPWHITESPACE%%> word.dragTo( 300 , 300 , 50 );<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> word.swipeDown( 50 );<br />专业处理滚动一百年。
视频大放送:
视频代码:
1 <br /><%%KEEPWHITESPACE%%> UiScrollable scrollable = new UiScrollable(<br /><%%KEEPWHITESPACE%%> new UiSelector().className( "android.widget.ListView" ));<br /><%%KEEPWHITESPACE%%> scrollable.flingForward();<br /><%%KEEPWHITESPACE%%> sleep( 500 );<br /><%%KEEPWHITESPACE%%> scrollable.flingBackward();<br /><%%KEEPWHITESPACE%%> sleep( 500 );<br /><%%KEEPWHITESPACE%%> scrollable.flingForward();<br /><%%KEEPWHITESPACE%%> UiObject target = new UiObject( new UiSelector().text( "德国工业就是这么强大!不得不服" ));<br /><%%KEEPWHITESPACE%%> scrollable.scrollIntoView(target);<br /><%%KEEPWHITESPACE%%> target.click();<br />通常用于获取满足某种搜索条件的组件集合,通过链式搜索确定最终需要的组件。 先按照一定的条件枚举容器内的子元素,再从符合条件的子元素中进一步定位。 一般使用容器类组件作为父类,用于寻找不好定位的子元素。
通常我们会让脚本来按照我们所需要的顺序来执行,但有时候,总有一些天灾人祸,比如10086发短信来了。 所以,我们的脚本必须要有一定的容错性。
UiWatcher正是这样一个容错的对象,当我们在顺序执行脚本时,如果中间突然插入了一些不明事件,我们可以使用UiWatcher来拦截异常,处理完异常后,再返回原来的脚本执行顺序。
Configuration,自然是对默认操作的配置,通常情况下,我们使用默认的Configuration就足够了,当然,如果你有一些特殊需求,就可以通过Configuration类来设置。它能更改我们前面提到的所有默认属性的设置。包括默认延迟、输入延迟、等待超时等等。
下面是一个典型的UiAutomator测试报告:
INSTRUMENTATION_STATUS: numtests=1 INSTRUMENTATION_STATUS: stream= com.hj.autotest.AutoTest: INSTRUMENTATION_STATUS: id=UiAutomatorTestRunner INSTRUMENTATION_STATUS: test=testDevice INSTRUMENTATION_STATUS: class=com.hj.autotest.AutoTest INSTRUMENTATION_STATUS: current=1 INSTRUMENTATION_STATUS_CODE: 1 INSTRUMENTATION_STATUS: numtests=1 INSTRUMENTATION_STATUS: stream=. INSTRUMENTATION_STATUS: id=UiAutomatorTestRunner INSTRUMENTATION_STATUS: test=testDevice INSTRUMENTATION_STATUS: class=com.hj.autotest.AutoTest INSTRUMENTATION_STATUS: current=1 INSTRUMENTATION_STATUS_CODE: 0 INSTRUMENTATION_STATUS: stream= Test results for WatcherResultPrinter=. Time: 31.489 OK (1 test) INSTRUMENTATION_STATUS_CODE: -1这些报告被INSTRUMENTATION_STATUS_CODE分为了三个部分,1表示运行前,-1表示运行完成。
如果出错了,你可以在报告中找到相应的错误信息。
你同样需要知道的是,UiAutomator也是JUnit工程,你同样可以在里面使用断言来进行某些变量、结果值的测试,这些同样会在报告中体现出来。
最后,UiAutomator大部分内容都讲完了,最后一个视频:
视频代码:
1 <br /><%%KEEPWHITESPACE%%> UiDevice.getInstance().pressHome();<br /><%%KEEPWHITESPACE%%> new UiObject( new UiSelector().description( "Apps" ))<br /><%%KEEPWHITESPACE%%> .clickAndWaitForNewWindow();<br /><%%KEEPWHITESPACE%%> UiScrollable scrollable = new UiScrollable(<br /><%%KEEPWHITESPACE%%> new UiSelector()<br /><%%KEEPWHITESPACE%%> .resourceId(<br /><%%KEEPWHITESPACE%%> "com.google.android.googlequicksearchbox:id/apps_customize_pane_content" ));<br /><%%KEEPWHITESPACE%%> scrollable.setAsHorizontalList();<br /><%%KEEPWHITESPACE%%> UiObject word = new UiObject( new UiSelector().text( "沪江开心词场" ));<br /><%%KEEPWHITESPACE%%> while (!word.exists()) {<br /><%%KEEPWHITESPACE%%> scrollable.scrollForward();<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> word.clickAndWaitForNewWindow();<br /><%%KEEPWHITESPACE%%> UiObject username = new UiObject( new UiSelector().text( "沪江用户名/邮箱/手机" ));<br /><%%KEEPWHITESPACE%%> username.setText( "xys10086" );<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiObject pwd = new UiObject(<br /><%%KEEPWHITESPACE%%> new UiSelector().resourceId( "com.hjwordgames:id/edit_password" ));<br /><%%KEEPWHITESPACE%%> pwd.setText( "Aa123465" );<br /><%%KEEPWHITESPACE%%> sleep( 1000 );<br /><%%KEEPWHITESPACE%%> UiObject login = new UiObject( new UiSelector().text( "登 录" ));<br /><%%KEEPWHITESPACE%%> login.clickAndWaitForNewWindow();<br /><%%KEEPWHITESPACE%%> if ( new UiObject( new UiSelector().className(<br /><%%KEEPWHITESPACE%%> "android.widget.FrameLayout" ).index( 1 )).exists()) {<br /><%%KEEPWHITESPACE%%> new UiObject( new UiSelector().text( "注册" ))<br /><%%KEEPWHITESPACE%%> .clickAndWaitForNewWindow();<br /><%%KEEPWHITESPACE%%> new UiObject(<br /><%%KEEPWHITESPACE%%> new UiSelector()<br /><%%KEEPWHITESPACE%%> .resourceId( "com.hjwordgames:id/registerEditUsername" ))<br /><%%KEEPWHITESPACE%%> .setText( "xys100861" );<br /><%%KEEPWHITESPACE%%> new UiObject(<br /><%%KEEPWHITESPACE%%> new UiSelector()<br /><%%KEEPWHITESPACE%%> .resourceId( "com.hjwordgames:id/registerEditPassword" ))<br /><%%KEEPWHITESPACE%%> .setText( "Aa123456" );<br /><%%KEEPWHITESPACE%%> new UiObject(<br /><%%KEEPWHITESPACE%%> new UiSelector()<br /><%%KEEPWHITESPACE%%> .resourceId( "com.hjwordgames:id/regiserEditEmail" ))<br /><%%KEEPWHITESPACE%%> .setText( "35998151@qq.com" );<br /><%%KEEPWHITESPACE%%> new UiObject( new UiSelector().text( "确认注册" ))<br /><%%KEEPWHITESPACE%%> .clickAndWaitForNewWindow();<br /><%%KEEPWHITESPACE%%> UiObject ok = new UiObject(<br /><%%KEEPWHITESPACE%%> new UiSelector().resourceId( "com.hjwordgames:id/btnOK" ));<br /><%%KEEPWHITESPACE%%> if (ok.waitForExists( 500 )) {<br /><%%KEEPWHITESPACE%%> ok.clickAndWaitForNewWindow();<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> }<br />在Eclipse中创建一个java工程,并添加platforms文件夹下面的android.jar和uiautomator.jar两个引用。如下图:
UiAutomator中的测试类都要继承UiAutomatorTestCase,每个测试用例的方法的方法名都要以test开头。如下图:
在测试用例的方法中,我们就可以编写测试脚本代码。
在终端中,输入:
android create uitest-project -n <name> -t <android-sdk-ID> -p <path>这里的android sdk id指的是在终端中,输入android list返回的你使用的sdk的id。 这里还要PS下,一定要配置好环境变量,这是我们后面一键自动化的基础。
例如:
android create uitest-project -n Demo -t 30 -p "F:\EclipseWorkSpace\AutoTest"如下图:
生成的build.xml文件我们还无法直接使用,我们需要修改它的一个属性,打开build.xml文件,将help改为build,如下图:
使用Ant,我们利用build.xml打包生成jar,命令如下:
ant -buildfile "F:\EclipseWorkSpace\AutoTest"编译过程如下图:
我们需要将jar包push到手机中的/data/local/tmp/目录才能启动测试。如下图:
adb push "F:\EclipseWorkSpace\AutoTest\bin\Demo.jar" /data/local/tmp/在终端中输入启动测试命令(#后如果不指定具体的用例名,则测试所有的方法),如下:
adb shell uiautomator runtest Demo.jar --nohup -c com.hj.autotest.AutoTest#testBrowser到此为止,整个测试用例的测试就全部结束了。
看完前面的步骤,相信很多人已经不想再看下去了,好吧,那你们损失大了,所谓自动化测试,就是为了减少人工的操作,像这样反复的编译、修改、push、运行,这跟手动去测试又有什么区别呢? OK,让自动化再上升一个境界。 我们可以发现,其实这些操作,与我们进行测试一样,也是一些机械动作,ok,那么我们完全可以使用同样的思路——使用脚本来解决这些问题。 我们创建一个脚本工具——UiAutomatorTool,来封装这些机械的步骤。代码非常简单,无非是使用Java调用终端命令,来执行前面的各种操作。 代码如下:
1 <br /> package com.hj.autotest;<br /><br /> import java.io.BufferedReader;<br /> import java.io.BufferedWriter;<br /> import java.io.File;<br /> import java.io.FileInputStream;<br /> import java.io.FileWriter;<br /> import java.io.IOException;<br /> import java.io.InputStream;<br /> import java.io.InputStreamReader;<br /><br /> public class UiAutomatorTool {<br /><br /><%%KEEPWHITESPACE%%> // 工作空间目录<br /><%%KEEPWHITESPACE%%> private static String WORKSPACE_PATH;<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * 指定自动测试的参数<br /><%%KEEPWHITESPACE%%> *<br /><%%KEEPWHITESPACE%%> * @param jarName<br /><%%KEEPWHITESPACE%%> * 生成jar的名字<br /><%%KEEPWHITESPACE%%> * @param testPackageclass<br /><%%KEEPWHITESPACE%%> * 测试包名+类名<br /><%%KEEPWHITESPACE%%> * @param testFunction<br /><%%KEEPWHITESPACE%%> * 测试方法名,空字符串代表测试所有方法<br /><%%KEEPWHITESPACE%%> * @param androidId<br /><%%KEEPWHITESPACE%%> * SDK id<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> public UiAutomatorTool(String jarName, String testPackageclass,<br /><%%KEEPWHITESPACE%%> String testFunction, String androidId) {<br /><%%KEEPWHITESPACE%%> System.out.println("*******************");<br /><%%KEEPWHITESPACE%%> System.out.println(" --AutoTest Start--");<br /><%%KEEPWHITESPACE%%> System.out.println("*******************");<br /><%%KEEPWHITESPACE%%> // 获取工作空间目录路径<br /><%%KEEPWHITESPACE%%> WORKSPACE_PATH = getWorkSpase();<br /><%%KEEPWHITESPACE%%> System.out.println("自动测试项目工作空间:\t\n" + getWorkSpase());<br /><br /><%%KEEPWHITESPACE%%> // ***********启动测试*********** //<br /><%%KEEPWHITESPACE%%> // 创建Build.xml文件<br /><%%KEEPWHITESPACE%%> creatBuildXml(jarName, androidId);<br /><%%KEEPWHITESPACE%%> // 修改Build.xml文件中的Build类型<br /><%%KEEPWHITESPACE%%> modfileBuild();<br /><%%KEEPWHITESPACE%%> // 使用Ant编译jar包<br /><%%KEEPWHITESPACE%%> antBuild();<br /><%%KEEPWHITESPACE%%> // push jar到手机<br /><%%KEEPWHITESPACE%%> pushJarToAndroid(WORKSPACE_PATH + "\\bin\\" + jarName + ".jar");<br /><%%KEEPWHITESPACE%%> // 测试方法,为空则测试全部方法<br /><%%KEEPWHITESPACE%%> if (androidId.equals("")) {<br /><%%KEEPWHITESPACE%%> runTest(jarName, testPackageclass);<br /><%%KEEPWHITESPACE%%> } else {<br /><%%KEEPWHITESPACE%%> runTest(jarName, testPackageclass + "#" + testFunction);<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> // ***********启动测试*********** //<br /><%%KEEPWHITESPACE%%> System.out.println("*******************");<br /><%%KEEPWHITESPACE%%> System.out.println("---AutoTest End----");<br /><%%KEEPWHITESPACE%%> System.out.println("*******************");<br /><%%KEEPWHITESPACE%%> }<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * 创建build.xml文件<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> public void creatBuildXml(String jarName, String androidID) {<br /><%%KEEPWHITESPACE%%> System.out.println("--------创建build.xml 开始---------");<br /><%%KEEPWHITESPACE%%> execCmd("cmd /c android create uitest-project -n " + jarName + " -t "<br /><%%KEEPWHITESPACE%%> + androidID + " -p " + "\"" + WORKSPACE_PATH + "\"");<br /><%%KEEPWHITESPACE%%> System.out.println("--------创建build.xml 完成---------");<br /><%%KEEPWHITESPACE%%> }<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * 修改build.xml文件位build type<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> public void modfileBuild() {<br /><%%KEEPWHITESPACE%%> System.out.println("--------修改build.xml 开始---------");<br /><%%KEEPWHITESPACE%%> StringBuffer stringBuffer = new StringBuffer();<br /><%%KEEPWHITESPACE%%> try {<br /><%%KEEPWHITESPACE%%> File file = new File("build.xml");<br /><%%KEEPWHITESPACE%%> if (file.isFile() &amp;&amp; file.exists()) {<br /><%%KEEPWHITESPACE%%> InputStreamReader read = new InputStreamReader(<br /><%%KEEPWHITESPACE%%> new FileInputStream(file));<br /><%%KEEPWHITESPACE%%> BufferedReader bufferedReader = new BufferedReader(read);<br /><%%KEEPWHITESPACE%%> String lineTxt;<br /><%%KEEPWHITESPACE%%> while ((lineTxt = bufferedReader.readLine()) != null) {<br /><%%KEEPWHITESPACE%%> if (lineTxt.matches(".*help.*")) {<br /><%%KEEPWHITESPACE%%> lineTxt = lineTxt.replaceAll("help", "build");<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> stringBuffer = stringBuffer.append(lineTxt).append("\t\n");<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> read.close();<br /><%%KEEPWHITESPACE%%> } else {<br /><%%KEEPWHITESPACE%%> System.out.println("找不到build.xml文件");<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> } catch (Exception e) {<br /><%%KEEPWHITESPACE%%> System.out.println("读取build.xml内容出错");<br /><%%KEEPWHITESPACE%%> e.printStackTrace();<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> // 重新写回build.xml<br /><%%KEEPWHITESPACE%%> rewriteBuildxml("build.xml", new String(stringBuffer));<br /><%%KEEPWHITESPACE%%> System.out.println("--------修改build.xml 完成---------");<br /><%%KEEPWHITESPACE%%> }<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * 使用Ant编译jar包<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> public void antBuild() {<br /><%%KEEPWHITESPACE%%> System.out.println("--------编译build.xml 开始---------");<br /><%%KEEPWHITESPACE%%> execCmd("cmd /c ant -buildfile " + "\"" + WORKSPACE_PATH + "\"");<br /><%%KEEPWHITESPACE%%> System.out.println("--------编译build.xml 完成---------");<br /><%%KEEPWHITESPACE%%> }<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * adb push jar包到Android手机<br /><%%KEEPWHITESPACE%%> *<br /><%%KEEPWHITESPACE%%> * @param localPath<br /><%%KEEPWHITESPACE%%> * localPath<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> public void pushJarToAndroid(String localPath) {<br /><%%KEEPWHITESPACE%%> System.out.println("--------push jar 开始---------");<br /><%%KEEPWHITESPACE%%> localPath = "\"" + localPath + "\"";<br /><%%KEEPWHITESPACE%%> System.out.println("jar包路径:" + localPath);<br /><%%KEEPWHITESPACE%%> String pushCmd = "adb push " + localPath + " /data/local/tmp/";<br /><%%KEEPWHITESPACE%%> execCmd(pushCmd);<br /><%%KEEPWHITESPACE%%> System.out.println("--------push jar 完成---------");<br /><%%KEEPWHITESPACE%%> }<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * 测试方法<br /><%%KEEPWHITESPACE%%> *<br /><%%KEEPWHITESPACE%%> * @param jarName<br /><%%KEEPWHITESPACE%%> * jar包名<br /><%%KEEPWHITESPACE%%> * @param testName<br /><%%KEEPWHITESPACE%%> * testName<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> public void runTest(String jarName, String testName) {<br /><%%KEEPWHITESPACE%%> System.out.println("--------测试方法 开始---------");<br /><%%KEEPWHITESPACE%%> String runCmd = "adb shell uiautomator runtest ";<br /><%%KEEPWHITESPACE%%> String testCmd = jarName + ".jar " + "--nohup -c " + testName;<br /><%%KEEPWHITESPACE%%> execCmd(runCmd + testCmd);<br /><%%KEEPWHITESPACE%%> System.out.println("--------测试方法 完成---------");<br /><%%KEEPWHITESPACE%%> }<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * 获取WorkSpace目录<br /><%%KEEPWHITESPACE%%> *<br /><%%KEEPWHITESPACE%%> * @return WorkSpace目录<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> public String getWorkSpase() {<br /><%%KEEPWHITESPACE%%> File directory = new File("");<br /><%%KEEPWHITESPACE%%> return directory.getAbsolutePath();<br /><%%KEEPWHITESPACE%%> }<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * Shell命令封装类<br /><%%KEEPWHITESPACE%%> *<br /><%%KEEPWHITESPACE%%> * @param cmd<br /><%%KEEPWHITESPACE%%> * Shell命令<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> public void execCmd(String cmd) {<br /><%%KEEPWHITESPACE%%> System.out.println("ExecCmd:" + cmd);<br /><%%KEEPWHITESPACE%%> try {<br /><%%KEEPWHITESPACE%%> Process p = Runtime.getRuntime().exec(cmd);<br /><%%KEEPWHITESPACE%%> // 执行成功返回流<br /><%%KEEPWHITESPACE%%> InputStream input = p.getInputStream();<br /><%%KEEPWHITESPACE%%> BufferedReader reader = new BufferedReader(new InputStreamReader(<br /><%%KEEPWHITESPACE%%> input, "GBK"));<br /><%%KEEPWHITESPACE%%> String line;<br /><%%KEEPWHITESPACE%%> while ((line = reader.readLine()) != null) {<br /><%%KEEPWHITESPACE%%> System.out.println(line);<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> // 执行失败返回流<br /><%%KEEPWHITESPACE%%> InputStream errorInput = p.getErrorStream();<br /><%%KEEPWHITESPACE%%> BufferedReader errorReader = new BufferedReader(<br /><%%KEEPWHITESPACE%%> new InputStreamReader(errorInput, "GBK"));<br /><%%KEEPWHITESPACE%%> String eline;<br /><%%KEEPWHITESPACE%%> while ((eline = errorReader.readLine()) != null) {<br /><%%KEEPWHITESPACE%%> System.out.println(eline);<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> } catch (IOException e) {<br /><%%KEEPWHITESPACE%%> e.printStackTrace();<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> }<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * 重新写回Build.xml<br /><%%KEEPWHITESPACE%%> *<br /><%%KEEPWHITESPACE%%> * @param path<br /><%%KEEPWHITESPACE%%> * path<br /><%%KEEPWHITESPACE%%> * @param content<br /><%%KEEPWHITESPACE%%> * content<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> public void rewriteBuildxml(String path, String content) {<br /><%%KEEPWHITESPACE%%> File dirFile = new File(path);<br /><%%KEEPWHITESPACE%%> if (!dirFile.exists()) {<br /><%%KEEPWHITESPACE%%> dirFile.mkdir();<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> try {<br /><%%KEEPWHITESPACE%%> BufferedWriter bw1 = new BufferedWriter(new FileWriter(path));<br /><%%KEEPWHITESPACE%%> bw1.write(content);<br /><%%KEEPWHITESPACE%%> bw1.flush();<br /><%%KEEPWHITESPACE%%> bw1.close();<br /><%%KEEPWHITESPACE%%> } catch (IOException e) {<br /><%%KEEPWHITESPACE%%> e.printStackTrace();<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> }<br />}<br />那我们怎么使用呢?拿一个测试类来说:
1 <br /> public class AutoTest extends UiAutomatorTestCase {<br /><br /><%%KEEPWHITESPACE%%> public static void main(String[] args) {<br /><%%KEEPWHITESPACE%%> new UiAutomatorTool( "Demo" , "com.hj.autotest.AutoTest" , "testUiSelector" , "30" );<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> ……<br />}<br />我们只需要在测试类中new一个UiAutomatorTool,并指定jar包名、包名、用例名、Android id即可。 接下来,只需要运行这样Java程序,就完成了整个过程的自动化,一键编译、一键运行。
好吧,再来一个视频:
前面我们已经让编译、push、运行自动化了,但是说到底,就连编写脚本也是一件非常繁琐的事情啊。OK,我们同样可以创建一个H5的页面,通过编写图形化的页面,来替代我们每个动作脚本的编写,毕竟这些脚本也是死的啊。
这些脚本可不仅仅能做测试。 经过前面一系列的代码、演示,我们已经可以通过脚本来进行测试用例的自动化测试,但是,自动化不仅仅可以用来测试,当我们在调试程序的时候,经常需要登陆App以后才能进行测试,我们同样可以把这些操作放到脚本中,启动调试后,直接运行脚本,完成这样繁琐的输入、登陆步骤。
http://blog.csdn.net/eclipsexys/article/details/45622813
转载请注明:Android开发中文站 » 解放双手——Android自动化测试