一、问题背景

刚开始用的是百度cafe搭建的框架,已经用了一些版本,最后的test版本在7.4的apk上能跑,但是在最新发布的7.5的版本上跑不了,直接提示nullPointer错误,通过打日志的方式发现local这个变量就是null,也就是说根本没有被初始化为正确的值,那么原因是什么呢?

二、问题排查

从两个方面进行排查:

1、我们的test程序:

因为本身用cafe搭建的已经有一段时间,而且当时因为用的是非root的手机,所以没有办法进行debug,所以就想本来cafe就是对robotium的一个封装,那就试试robotium的最简单的程序,看能不能找到问题原因。

从网上下载了robotium的最新的源码,notepad和notepadtest,这个导入过程也记录一下,下载下来的是一个zip的压缩包,里面包含两个工程,导入的时候,通过file-import-general-existing into workspace-next-select archive file,具体见下图:

然后Browse,找到正确的文件,确定finish即可。

官网给出的例子是有源码的,演变成没有源码的版本,NotePadTest中的主要内容如下:

/** This is an example test project created in Eclipse to test NotePad which is a sample * project located in AndroidSDK/samples/android-11/NotePad* * * You can run these test cases either on the emulator or on device. Right click* the test project and select Run As --> Run As Android JUnit Test* * @author Renas Reda, renas.reda@robotium.com* */package com.robotium.test;import com.robotium.solo.Solo;
import android.test.ActivityInstrumentationTestCase2;public class NotePadTest extends ActivityInstrumentationTestCase2{private Solo solo;private static String packageName = "com.example.android.notepad";private static String mainActivity = "com.example.android.notepad.NotesList";private static Class<?> launchableActivity;static{try{launchableActivity = Class.forName(mainActivity);}catch(ClassNotFoundException e){throw new RuntimeException(e);}};public NotePadTest(){super(packageName, launchableActivity);}@Overridepublic void setUp() throws Exception {//setUp() is run before a test case is started. //This is where the solo object is created.solo = new Solo(getInstrumentation(), getActivity());}@Overridepublic void tearDown() throws Exception {//tearDown() is run after a test case has finished. //finishOpenedActivities() will finish all the activities that have been opened during the test execution.
        solo.finishOpenedActivities();}public void testAddNote() throws Exception {//Unlock the lock screen
        solo.unlockScreen();solo.clickOnMenuItem("Add note");//Assert that NoteEditor activity is openedsolo.assertCurrentActivity("Expected NoteEditor activity", "NoteEditor"); //In text field 0, enter Note 1solo.enterText(0, "Note 1");solo.goBack(); //Clicks on menu itemsolo.clickOnMenuItem("Add note");//In text field 0, type Note 2solo.typeText(0, "Note 2");//Go back to first activity
        solo.goBack(); //Takes a screenshot and saves it in "/sdcard/Robotium-Screenshots/".
        solo.takeScreenshot();boolean notesFound = solo.searchText("Note 1") && solo.searchText("Note 2");//Assert that Note 1 & Note 2 are foundassertTrue("Note 1 and/or Note 2 are not found", notesFound); }public void testEditNote() throws Exception {// Click on the second list linesolo.clickLongInList(2); solo.clickOnText("Edit title");// Change orientation of activity
        solo.setActivityOrientation(Solo.LANDSCAPE);//In first text field (0), add testsolo.enterText(0, " test");  //solo.goBack();
        solo.setActivityOrientation(Solo.PORTRAIT);// (Regexp) case insensitiveboolean noteFound = solo.waitForText("(?i).*?note 1 test"); //Assert that Note 1 test is foundassertTrue("Note 1 test is not found", noteFound); }public void testRemoveNote() throws Exception {//(Regexp) case insensitive/text that contains "test"solo.clickOnText("(?i).*?test.*");//Delete Note 1 testsolo.clickOnMenuItem("Delete");//Note 1 test should not be foundboolean noteFound = solo.searchText("Note 1 test");//Assert that Note 1 test is not foundassertFalse("Note 1 Test is found", noteFound);  solo.clickLongOnText("Note 2");//Clicks on Delete in the context menusolo.clickOnText("Delete");  //Will wait 100 milliseconds for the text: "Note 2"noteFound = solo.waitForText("Note 2", 1, 100);//Assert that Note 2 is not foundassertFalse("Note 2 is found", noteFound);  }
}

接下来我们的程序也按照类似这样的形式改造,单步调试(单步调试的快捷键请自行查找,我的是F7进函数,F8继续下一步),Run as Android junit test的情况下,发现需要手机root才可以,即需要在adb shell下能够显示#号才可以,因此我们采用了AVD进行调试,具体问题就是在setup的时候,solo = new Solo(getInstrumentation(), getActivity())方法,在第二个参数getActivity()这里,进入getActivity()方法,一步步往下调试的时候,发现卡在了下面方法中的加黄色的代码语句这里:

/*** Start a new activity and wait for it to begin running before returning.* In addition to being synchronous, this method as some semantic* differences from the standard {@link Context#startActivity} call: the* activity component is resolved before talking with the activity manager* (its class name is specified in the Intent that this method ultimately* starts), and it does not allow you to start activities that run in a* different process.  In addition, if the given Intent resolves to* multiple activities, instead of displaying a dialog for the user to* select an activity, an exception will be thrown.* * <p>The function returns as soon as the activity goes idle following the* call to its {@link Activity#onCreate}.  Generally this means it has gone* through the full initialization including {@link Activity#onResume} and* drawn and displayed its initial window.* * @param intent Description of the activity to start.* * @see Context#startActivity*/public Activity startActivitySync(Intent intent) {validateNotAppThread();synchronized (mSync) {intent = new Intent(intent);ActivityInfo ai = intent.resolveActivityInfo(getTargetContext().getPackageManager(), 0);if (ai == null) {throw new RuntimeException("Unable to resolve activity for: " + intent);}String myProc = mThread.getProcessName();if (!ai.processName.equals(myProc)) {// todo: if this intent is ambiguous, look here to see if// there is a single match that is in our package.throw new RuntimeException("Intent in process "+ myProc + " resolved to different process "+ ai.processName + ": " + intent);}intent.setComponent(new ComponentName(ai.applicationInfo.packageName, ai.name));final ActivityWaiter aw = new ActivityWaiter(intent);if (mWaitingActivities == null) {mWaitingActivities = new ArrayList();}mWaitingActivities.add(aw);getTargetContext().startActivity(intent);do {try {mSync.wait();             //就是卡在了这里} catch (InterruptedException e) {}} while (mWaitingActivities.contains(aw));return aw.activity;}}

以上这段代码如注释中所说:这个方法是启动一个Activity让其运行起来,加了同步锁的synchronized (mSync),然后走到了最下面的mSync.wait()这里,就一直等待,因为前面有一个内容挡住了这个wait,所以它一直等不到就一直出不了循环;只有等待成功,从do-while循环中出来,才能够启动并且将Activity返回。

在自己排查的过程中从网上找了一个帖子,具体见这里:http://www.2cto.com/kf/201410/344608.html,以及stackoverflow上的一个问题:http://stackoverflow.com/questions/20860832/why-does-getactivity-block-during-junit-test-when-custom-imageview-calls-start,虽然我卡住的地方跟他不同,但得到了一些启示,同时从robotium的源码中发现,getActivity()这个参数也可以去掉,因为我去掉这个方法后,在test程序安装之后,手动将程序启动起来,发现test能够正常run起来,不会出现挂起;然后就将手动启动程序的方式改成了通过调用方法自动启动程序的方法,见下方:

protected void startActivity(){Intent it = new Intent();it.setClassName(packageName, mainActivity);it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);getInstrumentation().getContext().startActivity(it);}

然后在solo的setup方法的new Solo()方法之前调用startActivity(),具体见下方:

@Beforeprotected void setUp() throws Exception {startActivity();solo = new Solo(getInstrumentation());}

通过这种方法就可以暂时将case流程跑起来,但是在后面需要用到solo.waitForActivity("xxxx")以及solo.getCurrentActivity()方法也一样无法执行,这样的方式相当于放弃了很多solo中的比较好用的方法,所以需要再换一种思路。

上面的debug过程在7.4版本上重点过了一下,发现并没有卡在wait的位置,定位之后希望能从开发的代码上进行排查看能不能找到一些线索。

2、从开发的代码进行排查:

需要找到7.5与7.4的不同,确定修改了哪些内容可能导致出现这个问题,然而在你向另外一个人提问的时候,他一般会按照自己的理解说出自己认为的重点,并且不同模块由不同的人负责,甚至有些人会说不清自己改了什么,所以就找了开发组里对整个框架以及代码最熟悉的同事帮忙看这个问题。

三、与开发协调推进解决

因为手动启动并运行开发的程序是OK的,但是通过test程序run被测程序的时候就会根本跑不通基本流程,因此还是从最基本的内容查,包括LaunchActivity的相关,以及公共的一些跟启动相关的,开发哥哥在经过三天排查之后,终于发现了问题原因,注释掉一行插件初始化的代码就可以运行起来,加上就无法运行。

四、先把测试跑通

因为先自己本地down到代码,然后把存在问题的代码注释掉之后,先将测试跑起来。但是这个问题是因为robotium本身就是基于安卓底层去获取一些内容,在进行设置的时候,因为在同一个进程中,可能会与开发的一些调用方法或者设置存在冲突,排查起来还是需要大家一起努力(PS:前提是自己能够把问题定位出来)。

所以后来也用了appium跑了一下,结果能够跑通,appium基于client-server的机制,并不会出现以上的问题,那appium是否可能存在其他的问题呢?这个也需要再碰到再探讨。

转载于:https://www.cnblogs.com/keke-xiaoxiami/p/5735557.html

robotium(及百度cafe)运行testcase之后程序挂起没有响应的原因调查及解决相关推荐

  1. 【免费】win7 所有.net framework框架集合,免费下载,若要运行此应用程序,您必须首先安装net framework如何解决

    运行软件缺失框架: 若要运行此应用程序 您必须首先安装net framework如何解决 那天我看见网上下载一个框架都要收费还要100大洋,现在真的是干啥都要钱,索性就整理了一个全库供大家下载,做点好 ...

  2. 关于WSL(Windows子系统)无法运行32位程序的初步解决办法

    为了偷懒,开始使用上了WSL,不得不说这是个很方便的东西,但是,WSL不具备linux的全部功能,这次遇到的一个对我影响比较大的,应该就是它无法运行32位程序.因为做pwn题需要不断调试程序已经本地运 ...

  3. Robotium调用getActivity()导致程序挂起的方法

    1. 问题背景的叙述性说明 需要直接用在工作中没有项目的源代码robotium测试目标android平台launcher,该平台的基础上,当前日期的版本号android 4.4.2.之前我用来验证的可 ...

  4. Selenium启动Chrome浏览器提示“请停用以开发者模式运行的扩展程序”的解决办法

    安装了selenium,python运行下面代码: from selenium import webdriverbrowser = webdriver.Chrome() browser.get('ht ...

  5. linux如何运行java程序,Linux环境下运行简单java程序

    一.安装java 1.下载jdk8 选择对应jdk版本下载.(Tips:可在Windows下载完成后,通过FTP或者SSH到发送到Linux上) 2. 登录Linux,切换到root用户 su roo ...

  6. android程序怎么执行,电脑怎么运行安卓手机程序【详细介绍】

    电脑怎么运行安卓手机程序? 我们都知道安卓手机程序在手机在运行很好,但是如果有时候我们不想在手机上运行,想在电脑上运行又该怎么办呢? 下面,我们就以支付宝钱包为例来模拟运行吧. 1.首先下载最新版的B ...

  7. uniapp平台使用vant组件按需引入,并兼容到微信、百度、抖音小程序

    uniapp平台使用vant组件按需引入,并兼容到微信.百度.抖音小程序 请先了解vant在各小程序的兼容情况 前置条件 温馨提示 兼容到百度swan自定义组件 兼容到抖音tt自定义组件 请先了解va ...

  8. Qt开发北斗定位系统融合百度地图API及Qt程序打包发布

    Qt开发北斗定位系统融合百度地图API及Qt程序打包发布 1.上位机介绍 最近有个接了一个小型项目,内容很简单,就是解析北斗GPS的串口数据然后输出经纬度,但接过来觉得太简单,就发挥了主观能动性,增加 ...

  9. HBuilder X下载安装,运行微信小程序教程(官网)

    HBuilder是DCloud(数字天堂)推出的一款支持HTML5的Web开发IDE. [1] HBuilder的编写用到了Java.C.Web和Ruby.HBuilder本身主体是由Java编写. ...

最新文章

  1. MyBatis的运行的核心原理解析(三)
  2. boost::hana::experimental::print用法的测试程序
  3. Android之如何实现阿拉伯版本(RTL)的recycleView的网格布局
  4. c语言高级语言期中测试答案,上海理工大学C语言2011期中试题和答案
  5. IIS AppCreate子目录的错误(0x80020006)
  6. String和STL的一些基础知识
  7. JanusGraph: 可视化 Gephi 插件安装
  8. oracle清理asm归档日志,【Oracle】 rman 删除归档日志的命令
  9. python字典的键可以是列表吗_如何返回字典键作为Python中的列表?
  10. linux指令list by time,tar - Linux 常用命令
  11. MySQL字符串转日期
  12. centos7.2 使用rpm安装jdk8
  13. 猜数游戏c语言编程while,【游戏编程】猜数字游戏(C语言)
  14. ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
  15. Visual Studio Code编辑器的实用插件和工作中实用的技巧
  16. 常见分布的数学期望和方差
  17. Java中使用Atomic*实现原子锁线程安全
  18. 金山卫士界面源码解读及界面库分离(4)
  19. Git-删除暂存区文件
  20. 8大蓝牙电路应用热门方案,快速简单实现近距离无线连接

热门文章

  1. 小财靠勤,中财靠德,大财靠命,现在多少钱才是小财?
  2. 为了运行内存多两G,多花几百块值不值?
  3. 华为和谷歌在全球开发者眼里二选一,谁会获得胜利?
  4. python入门——P54论一只爬虫的自我修养1
  5. SqlServer解析XML,解析JSON数据格式
  6. ssis 导入excel_使用SSIS包将MS Excel数据导入数据库
  7. 配置SQL Server AlwaysOn高可用性组
  8. sql azure 语法_使用Azure门户监视安装了SQL Server的Azure计算机
  9. powershell 使用_使用PowerShell提取Azure成本
  10. 抖音直播APP软件系统为什么能这么火?反映出的问题又会是什么?