注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

风之云的足迹

点击这里添加博客描述

 
 
 

日志

 
 

Robotium针对应用UI线程一直被占用用例运行不了问题解决  

2013-02-17 16:37:31|  分类: 手机自动化测试 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
在使用Robotium编写测试用例的时候碰到了开发在应用中加入了一些动态的图片,导致了一直占用UI主线程,然后运行测试用例的时候卡在了初始化的getActivity方法。
public void setUp() throws Exception {
        solo
= new Solo(getInstrumentation(), getActivity());
 
}

当主线程一直被占用,没有空闲,应用也会抛出下面的警告信息
W/ActivityManager(175): Launch timeout has expired, giving up wake lock! W/ActivityManager(175): Activity idle timeout for ActivityRecord{413baf90 ***/***.Activity}

UI线程一直被占用会导致我们编写的robotium自动测试用例运行不了,经过查看源代码,最终是卡在了
1、首先卡在getActivity方法,该方法在android.test.ActivityInstrumentationTestCase2.java类中

@Override
public T getActivity() {
Activity a = super.getActivity();
if (a == null) {
// set initial touch mode
getInstrumentation().setInTouchMode(mInitialTouchMode);
final String targetPackage = getInstrumentation().getTargetContext().getPackageName();
// inject custom intent, if provided
if (mActivityIntent == null) {
//最终这里是卡在了这个方法,则继续往下看
a = launchActivity(targetPackage, mActivityClass, null);
} else {
a = launchActivityWithIntent(targetPackage, mActivityClass, mActivityIntent);
}
setActivity(a);
}
return (T) a;
}



2、launchActivity方法最终也调用了launchActivityWithIntent,在android.test.InstrumentationTestCase.java类中

public final <T extends Activity> T launchActivity(
String pkg,
Class<T> activityCls,
Bundle extras) {
Intent intent = new Intent(Intent.ACTION_MAIN);
if (extras != null) {
intent.putExtras(extras);
}
return launchActivityWithIntent(pkg, activityCls, intent);
}


@SuppressWarnings("unchecked")
public final <T extends Activity> T launchActivityWithIntent(
String pkg,
Class<T> activityCls,
Intent intent) {
intent.setClassName(pkg, activityCls.getName());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//这一步的话卡在了这里,则继续往下看
T activity = (T) getInstrumentation().startActivitySync(intent);
getInstrumentation().waitForIdleSync();
return activity;
}



3、startActivitySync方法在android.app.Instrumentation.java类中
通过类的注释说明,以及代码知道,当activity空闲的时候返回activity对象,如果不空闲的话这里会一直等待,导致卡主

/**
* 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;
}
}




通过尝试,可以临时使用下面的方法来替代getActivity

Instrumentation instrumentation = getInstrumentation();
//下面的代码用于启动需要测试的activity页面
final String targetPackage = getInstrumentation().getTargetContext().getPackageName();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(targetPackage, “com.***.***.***activity”);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getInstrumentation().getTargetContext().startActivity(intent);
//robotium可以支持不带activity参数的初始化
solo = new Solo(instrumentation);





  评论这张
 
阅读(2806)| 评论(5)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018