跨进程引发的问题
在应用中,打开的文档运行在一个新的进程中,在使用Espresso的时候就遇到了问题:无法拿到新进程中WebView的信息,原因没有仔细分析,但可以确定是跨进程的问题。在Robotium中这个问题同样存在。
不但如此,多进程还会导致当前activity的判断出错,本应判断在DocActivity中,但实际上得到的是在原进程的activity中。
在多种方法尝试无果后,只能暂时修改源码,将doc放在同进程打开。
View获取的问题
获取想要的View是编写用例最主要的难点所在,在获取View的时候也遇到了不少的坑:
重复出现的View
实际上通过getCurrentViews()获取到的View对象包括所有activity的所有View,比如主页面有3个tab,每个tab中有一个RecyclerView,这三个RecyclerView都是可以被获取到的(而不是想象中的只获取到当前可见的这个),甚至在打开新的activity后,后台的activity中的RecyclerView还是可以被获取到的。但是使用getView()方法获取的范围是当前activity。
这意味着什么呢?如果这些RecyclerView有相同的id,使用getView(int id)方法获取到的只是第一个,即使切到了第二个tab,获取到的还是第一个tab中的RecyclerView。
面对这个情况我们可以用三种方法:
· 如果它们id不同,使用getView(int id)就可以拿到特定的。如果id相同,可以传入第二个index参数来获取同id的第n个实例
· 使用getView(类名, int index)拿到该类所有实例中的第n个,因为各个RecyclerView加载的顺序是相对固定的,所以每次运行拿到的RecyclerView是同一个。拿上面的例子来说,如果要拿到第二个tab中的RecyclerView,要获取的应该是第2个。
· 先获取它的任意一个ParentView,然后通过getCurrentViews(类名,ViewGroup)方法拿到List,如果ViewGroup是唯一的,这个List中应该只会有我们想要的那个,也可以用ViewGroup来缩小我们搜索的范围。
View获取的技巧
总结一下
· 定位View最为方便的就是使用getView(int id/类名)这个方式,如果id/类名的实例唯一,就可以直接拿到。
· 如果同id/类名有很多个view存在,要使用getView(int id/类名, int index),拿到第n个view实例。
· 如果该view所处的任一个ViewGroup很好获取(有唯一id/类名),可以通过getCurrentViews(类名, ViewGroup)这个方式迅速缩小范围,拿到想要的View。
RecyclerView中获取ViewHolder
Robotium允许我们直接拿到View对象,所以我们可以直接使用RecyclerView的findViewHolderForAdapterPosition()方法去拿ViewHolder,但是事情并没有这么简单,我们知道RecyclerView的特点是没有在屏幕上显示的ViewHolder是没有被实例化的,这样拿到的会是null,所以为了拿到所有ViewHolder我们还需要使用
scrollDownRecyclerView()方法让RecyclerView滚动起来,但是使用这个方法还会有问题,有时候它会失效(怀疑是没有完成滚动就执行了下一条语句),所以还需要在调用这个方法之后设一个延迟(100ms就行),样例代码如下:
for (int i = 0; i < listAdapter.getItemCount(); i++) { RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(i); if (null == viewHolder) { mSolo.scrollDownRecyclerView(0); SystemClock.sleep(100); viewHolder = recyclerView.findViewHolderForAdapterPosition(i); } if (testAction.test(listAdapter, viewHolder, i)) { break; } } |
WebView中的WebElement获取需要延迟
之前介绍了等待WebView加载的方法,但是实际上这个方法返回后通过getWebElements()拿到的WebElements是空的,实际上想要拿到WebElement还要等待几秒种的时间。
输入字符的问题
直接输入字符的方法
private void inputString(String text) {
InstrumentationRegistry.getInstrumentation().sendStringSync(text);
}
会把string拆分成按键序列输入。
丢失字符的问题
调用上面的方法输入的字符过长的时候会偶发出现字符丢失的问题,暂时不知道解决方法,只能输入短一点的字符。
方法调用顺序的问题
写在AndroidTest文件夹下同一个测试类中的各个方法的调用顺序是未知的,而且没有找到好的办法可以直接在内部决定它们的调用顺序,本来这并不是一个大问题,但是在写测试的过程中出现了一个比较致命的问题:连续打开WebView会导致WebView无法加载。这个问题应该是由于复用了WebView或者loading view的判断出了问题导致的。单独单次地运行单个测试方法并不会出现这个问题,所以考虑转而使用手写测试脚本 的方式来决定方法的调用顺序并且单次地运行单个测试方法。同时脚本还应该支持重新编译测试Apk并且安装到手机,并且可以指定测试的方法与执行顺序。
最终编写完成的脚本如下:
#!/bin/bash function rebuild_install() { ./gradlew --build-cache :app:assemblePublishxxxDebug :app:assemblePublishxxxDebugAndroidTest adb push app/build/outputs/apk/publishxxx/debug/app-publish-xxx-debug.apk /data/local/tmp/com.xxx.xx.xxxx adb shell pm install -t -r "/data/local/tmp/com.xxx.xx.xxxx" adb push app/build/outputs/apk/androidTest/publishxxx/debug/app-publish-xxx-debug-androidTest.apk /data/local/tmp/com.xxx.xx.xxxx adb shell pm install -t -r "/data/local/tmp/com.xxx.xx.xxxx" } cd .. if test -z "$1" then echo Not Rebuild else if [ "$1"="rebuild" ] then rebuild_install fi fi test_funcs=($(awk '{print $0}' ui_test/funtion_names.txt)) for funcs in ${test_funcs[@]} do echo ┌-------------------------------------- echo Start $funcs adb shell am force-stop com.xxx.xx.xxxx adb shell am instrument -w -r -e debug false -e class com.xxx.xx.xxxx.MainInstrumentedTest#$funcs com.xxx.xx.xxxx.test/android.support.test.runner.AndroidJUnitRunner | sed -En -e '/There was/,/FAILURES/p;/OK/p' echo └-------------------------------------- done |
需要测试的方法按顺序放在funtion_names.txt文件中:
checkLogout
checkNewDoc
checkCreateDoc
checkOpenShare
在使用时可以传入rebuild参数来重新构建并安装,未传入可以直接开始测试:
./test.sh rebuild // 重新构建并安装
./test.sh //直接测试
运行结果示例:
Not Rebuild ┌-------------------------------------- Start checkLogout OK (1 test) └-------------------------------------- ┌-------------------------------------- Start checkNewDoc OK (1 test) └-------------------------------------- ┌-------------------------------------- Start checkCreateDoc OK (1 test) └-------------------------------------- ┌-------------------------------------- Start checkOpenShare OK (1 test) └----------------------------------- |
上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。