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