标签:robotium stuck hung getactivity
在工作中需要在没有项目源码的情况下直接使用robotium测试目标android平台launcher,平台的版本基于当前最新的android 4.4.2。之前在验证可行性的时候使用本人同样使用android4.4.2的测试手机htc incredable s针对一个只有apk的notepad应用做过同样的验证,在测试手机上运行完全没有问题。该测试代码如下:
package com.example.android.notepad.tryout;
import com.robotium.solo.Solo;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.TextView;
import android.app.Activity;
@SuppressWarnings("rawtypes")
public class NotePadTest extends ActivityInstrumentationTestCase2{
private static Solo solo = null;
public Activity activity;
private static final int NUMBER_TOTAL_CASES = 2;
private static int run = 0;
private static Class<?> launchActivityClass;
//对应re-sign.jar生成出来的信息框里的两个值
private static String mainActiviy = "com.example.android.notepad.NotesList";
private static String packageName = "com.example.android.notepad";
static {
try {
launchActivityClass = Class.forName(mainActiviy);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
public NotePadTest() {
super(packageName, launchActivityClass);
}
@Override
public void setUp() throws Exception {
//setUp() is run before a test case is started.
//This is where the solo object is created.
super.setUp();
//The variable solo has to be static, since every time after a case's finished, this class TCCreateNote would be re-instantiated
// which would lead to soto to re-instantiated to be null if it's not set as static
//TextView title = (TextView)getActivity().findViewById(Ref.id.title);
if(solo == null) {
NotePadTest.solo = new Solo(getInstrumentation(),getActivity());
}
}
@Override
public void tearDown() throws Exception {
//Check whether it's the last case executed.
run += countTestCases();
if(run >= NUMBER_TOTAL_CASES) {
solo.finishOpenedActivities();
}
}
public void testAddNoteCNTitle() throws Exception {
//Thread.sleep(5000);
solo.clickOnMenuItem("Add note");
solo.enterText(0, "中文标签笔记");
solo.clickOnMenuItem("Save");
solo.clickInList(0);
solo.clearEditText(0);
solo.enterText(0, "Text 1");
solo.clickOnMenuItem("Save");
solo.assertCurrentActivity("Expected NotesList Activity", "NotesList");
solo.clickLongOnText("中文标签笔记");
solo.clickOnText("Delete");
}
public void testAddNoteEngTitle() throws Exception {
solo.clickOnMenuItem("Add note");
solo.enterText(0, "English Title Note");
solo.clickOnMenuItem("Save");
solo.clickInList(0);
solo.clearEditText(0);
solo.enterText(0, "Text 1");
solo.clickOnMenuItem("Save");
solo.assertCurrentActivity("Expected NotesList Activity", "NotesList");
solo.clickLongOnText("English Title Note");
solo.clickOnText("Delete");
}
}
@Override
public void setUp() throws Exception {
//setUp() is run before a test case is started.
//This is where the solo object is created.
super.setUp();
//The variable solo has to be static, since every time after a case's finished, this class TCCreateNote would be re-instantiated
// which would lead to soto to re-instantiated to be null if it's not set as static
if(solo == null) {
NotePadTest.solo = new Solo(getInstrumentation(),getActivity());
}
}/**
* Utility method for launching an activity with a specific Intent.
*
* <p><b>NOTE:</b> The parameter <i>pkg</i> must refer to the package identifier of the
* package hosting the activity to be launched, which is specified in the AndroidManifest.xml
* file. This is not necessarily the same as the java package name.
*
* @param pkg The package hosting the activity to be launched.
* @param activityCls The activity class to launch.
* @param intent The intent to launch with
* @return The activity, or null if non launched.
*/
@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;
} /**
* Synchronously wait for the application to be idle. Can not be called
* from the main application thread -- use {@link #start} to execute
* instrumentation in its own thread.
*/
public void waitForIdleSync() {
validateNotAppThread();
Idler idler = new Idler(null);
mMessageQueue.addIdleHandler(idler);
mThread.getHandler().post(new EmptyRunnable());
idler.waitForIdle();
}这里按照本人的理解做的事情大概如下:solo = new Solo(getInstrumentation());因为我们的launcher在robotium在kill掉原来的launcher进程的时候就会自动起来,所以并不需要手动的去getActivity()去启动。这种方法在不能启动起来的apk如notepad上面就不行,不信你去掉getActivity()的调用,保证notepad不会启动或者放到前台。但是如果你在开始测试前先把notepad手动起来并放到前台,测试还是会正常进行的。比如以下的验证性代码:
package com.example.android.notepad.tryout;
import com.robotium.solo.Solo;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.TextView;
import android.app.Activity;
@SuppressWarnings("rawtypes")
public class NotePadTest extends ActivityInstrumentationTestCase2{
private static Solo solo = null;
public Activity activity;
private static final int NUMBER_TOTAL_CASES = 2;
private static int run = 0;
private static Class<?> launchActivityClass;
//对应re-sign.jar生成出来的信息框里的两个值
private static String mainActiviy = "com.example.android.notepad.NotesList";
private static String packageName = "com.example.android.notepad";
static {
try {
launchActivityClass = Class.forName(mainActiviy);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
public NotePadTest() {
super(packageName, launchActivityClass);
}
@Override
public void setUp() throws Exception {
//setUp() is run before a test case is started.
//This is where the solo object is created.
super.setUp();
//The variable solo has to be static, since every time after a case's finished, this class TCCreateNote would be re-instantiated
// which would lead to soto to re-instantiated to be null if it's not set as static
//TextView title = (TextView)getActivity().findViewById(Ref.id.title);
if(solo == null) {
NotePadTest.solo = new Solo(getInstrumentation());//, getActivity());
}
}
@Override
public void tearDown() throws Exception {
//Check whether it's the last case executed.
run += countTestCases();
if(run >= NUMBER_TOTAL_CASES) {
solo.finishOpenedActivities();
}
}
public void testAddNoteCNTitle() throws Exception {
//getActivity();
Thread.sleep(5000);
solo.clickOnMenuItem("Add note");
solo.enterText(0, "中文标签笔记");
solo.clickOnMenuItem("Save");
solo.clickInList(0);
solo.clearEditText(0);
solo.enterText(0, "Text 1");
solo.clickOnMenuItem("Save");
solo.assertCurrentActivity("Expected NotesList Activity", "NotesList");
solo.clickLongOnText("中文标签笔记");
solo.clickOnText("Delete");
}
}初始化solo的时候和testcase里面都没有去调用getActivity(),但是在testcase开始前先睡眠5秒,如果在这5秒的过程中你手动把notepad给启动起来,那么睡眠时间过后测试会继续正常运行。@Override
public MyActivity getActivity() {
if (mActivity == null) {
Intent intent = new Intent(getInstrumentation().getTargetContext(), MyActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// register activity that need to be monitored.
monitor = getInstrumentation().addMonitor(MyActivity.class.getName(), null, false);
getInstrumentation().getTargetContext().startActivity(intent);
mActivity = (MyActivity) getInstrumentation().waitForMonitor(monitor);
setActivity(mActivity);
}
return mActivity;
}鉴于本人现在只是做前期的可行性研究,够用就好,且周末手头上也没有目标机器在手进行验证,所以有兴趣的朋友就自己去尝试下吧,Robotium中调用getActivity()方法导致程序挂起的研究浅析
标签:robotium stuck hung getactivity
原文地址:http://blog.csdn.net/zhubaitian/article/details/40212271