SkySeraph May. 28th 2017html
Email:skyseraph00@163.comjava
更多精彩请直接访问SkySeraph我的站点:www.skyseraph.com android
Google Android Developers 在2015年3月就发布了UiAutomator 2.0版本(下文简称U2),而公司的核心产品中用到仍是UiAutomator老版本(下文简称U1),业界用U2的也不是不少,虽然有诸多问题和不便(如高版本OS中不支持Remote Debug等),但你们彷佛在苟延残喘中麻木了。 公司之前也有专家作过研究和探索,毕竟老项目是万级别的,涉及诸多算法和复杂业务逻辑,遇到几个问题最终不了了之。因而乎,又到了我手里了。 git
1. 基于 Instrumentation,使用Instrumentation test runner便可运行UiAutomator,反之,也即在基于Instrumentation的test中也能使用UiAutomator; 能够获取应用Context,可使用Android服务及接口。github
2. 基于 Junit4,测试用例无需继承于任何父类,方法名不限,使用Annotation进行; U1须要继承UiAutomatorTestCase,测试方法须要以test开头.算法
3. 与U1的Maven或Ant构建方式不一样,U2采用Gradle进行构建; U2输出为APK,Android工程,而U1为Java工程,输出jar包。shell
4. 新增UiObject2、Until、By、BySelector等接口, 详细请参考官方文档。
其中,U2必须明确EditText框才能向里面输入文字,U1直接指定父类也能够在子类中输入文字。框架
5. Log日志输出变动。U1可使用System.out.print输出流回显至执行端,而U2输出到Logcat。ide
6. 命令运行差别。性能
adb shell uiautomator runtest xx.jar -c package.name.ClassName adb shell am instrument -w -r -e class com.xx.xx com.xx.xx.test/ android.support.test.runner.AndroidJUnitRunner
代码中运行:
Runtime.getRuntime().exec(“*“)
device.executeShellCommand(“*“)
命令格式:instrument [options] component
,详细命令格式介绍参考官方文档。
新建Android Studio工程。
gradle中添加依赖。
androidTestCompile(‘com.android.support.test.espresso:espresso-core:2.2.2’{ exclude group: ‘com.android.support’, module: ‘support-annotations’ }) androidTestCompile ‘com.android.support.test:runner:0.5’ androidTestCompile ‘com.android.support.test:rules:0.5’ androidTestCompile ‘com.android.support.test.uiautomator:uiautomator-v18:2.1.2’ androidTestCompile ‘com.android.support:support-annotations:25.3.1’
如须要依赖jar包
androidTestCompile fileTree(dir: 'libs', include: ['*.jar'])
@RunWith(AndroidJUnit4.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class XXTest { public Bundle bundle; public UiDevice device; private Instrumentation instrumentation; @BeforeClass public static void beforeClass() { } @Before public void before() { // Initialize UiDevice instance instrumentation = InstrumentationRegistry.getInstrumentation(); device = UiDevice.getInstance(instrumentation); bundle = InstrumentationRegistry.getArguments(); assertThat(device, notNullValue()); } @After public void after() { L.i(TAG + "After"); } @AfterClass public static void afterClass() { L.i(TAG + "AfterClass"); } public Bundle getParams() { return bundle; } }
编译错误.
这个应该说是官方故意坑爹吧,U2的包名结构发生了变化,因此须要将以前全部用到的U1相关API包名进行替换,具体为
com.android.uiautomator.core. -> android.support.test.uiautomator.
反射相关.
这个有点坑爹,仍是U2包名结构问题(原项目不少地方用到了反射获取U1相关类/方法等),除非对原业务很是熟悉,不然只有遇到问题分析时才会发现此坑,读者之后若是遇到这种相似包结构变化的问题,先无论三七二十一,全局搜索相关字段全局了解再说。固然,若是用到了混淆,也要对应修改。
UiAutomatorTestCase相关.
问题:去除全部测试类中的extend UiAutomatorTestCase后异常。由于原项目依赖于UiAutomatorTestCase中的getPara API来获取U1命令传参。
方案:修改为U2的InstrumentationRegistry.getArguments方式。
日志相关.
问题:原项目中业务逻辑依赖System.out.println日志输出结果,而U2中System.out.println不会回显到终端显示,直接影响以前业务逻辑的执行。
方案:使用Instrumentation.sentStatus自定义状态。
属性文件.
描述:这个有点意思,原项目为Java工程,有不少属性配置在properties属性文件中,大概有20来个properties文件。而对属性文件的读取是在一个common的公共jar包中,采起的是Thread.currentThread().getContextClassLoader().getResourceAsStream方式。
问题:①属性配置文件没法打包进apk中 ②读取方式问题
解决:
方法1: 将属性配置文件所有放入assets目录,而后经过Context().getAssets().open方式读取;而原先的jar中的公共类,抽离出来做为业务类。
方法2: 经过gradle自定义打包,将全部属性配置文件打包进apk中,建议。
xml配置文件.
问题:原工程用到了RPC框架,有xml配置文件,存在与上述properties相似问题。
解决:gradle自定义打包。
权限问题.
问题:Android M+对权限进行了升级,本工程须要用到文件存储权限,仅在Manifest中声明WRITE_EXTERNAL_STORAGE权限还不够。
解决:
方法1:
@Before public void grantPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { getInstrumentation().getUiAutomation().executeShellCommand("pm grant "+getTargetContext().getPackageName()+"android.permission.WRITE_EXTERNAL_STORAGE"); } }
方法2:经过Rule
@Rule public final PermissionsRule permissionsRule = new PermissionsRule( new String[]{ Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE});
问题:在Android 4.4手机出现NoClassDefFoundError问题,Instrumentation消息为
INSTRUMENTATION_RESULT: longMsg=java.lang.NoClassDefFoundError: org.junit.runner.manipulation.Filter$1
解决: MultiDex手动拆包A
①gradle文件中添加multiDexKeepProguard
defaultConfig { multiDexEnabled true multiDexKeepProguard file('multidex.pro') }
②multidex文件中添加
-keep class android.support.multidex.** {*;} -keep public class org.junit.runner.** {*;}
本文首发于skyseraph.com:“UiAutomator2.0升级填坑记”
同步发表/转载 cnBlogs / …
By SkySeraph-2017