需要一种解决方法来阻止从ADT在AVD上运行的长单元测试。 JUnit视图中的停止按钮不起作用,调试视图中的停止按钮都不起作用。即使它打印出VM被终止。例如:
public class StopTest extends AndroidTestCase {
public void testSleep() throws Exception {
Thread.sleep(20000);
}
}
可能的解决方案:
在设备屏幕上显示取消按钮。
我设法在我的测试项目中创建了一个带有按钮的新Activity。不幸的是,测试套件是在我测试的应用程序的上下文中执行的。因此,要开始此活动,我需要编辑应用程序清单,这是我不想要的。所以我将此活动添加到测试清单中,然后从InstrumentationTestCase.getInstrumentation().getContext()
开始。
这样我的屏幕上会显示一个带按钮的活动,但它在另一个过程中启动。现在我需要一些东西来从活动向我测试的应用程序发送消息。
不想在我的应用中添加服务,因为正如我所说,我不想编辑应用清单。
是否可以向活动发送Binder
并使用它来发回消息?
答案 0 :(得分:0)
在setUp()
我用按钮开始活动。按下后,我重新开始操作,并在接收方中呼叫System.exit()
。
==> ./src/org/foo/StopButtonInstrumentationTestCase.java <==
...
public class StopButtonInstrumentationTestCase extends InstrumentationTestCase {
public void testSleep() throws Exception {
Thread.sleep(10000);
}
public void testSleep2() throws Exception {
Thread.sleep(10000);
}
@Override
protected void setUp() throws Exception {
super.setUp();
showStopButton(getInstrumentation(), getName());
}
@Override
protected void tearDown() throws Exception {
hideStopButton(getInstrumentation());
super.tearDown();
}
private static final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
System.exit(1);
}
};
public static void showStopButton(Instrumentation instrumentation, String testName) {
// register stop tests receiver
Context targetCtx = instrumentation.getTargetContext();
targetCtx.registerReceiver(receiver, new IntentFilter(StopperActivity.ACTION));
// show stop tests button
Context ctx = instrumentation.getContext();
Intent intent = new Intent(ctx, StopperActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra(StopperActivity.PARAM_TEST_NAME, testName);
ctx.startActivity(intent);
}
public static void hideStopButton(Instrumentation instrumentation) {
Context targetCtx = instrumentation.getTargetContext();
targetCtx.unregisterReceiver(receiver);
// hide stop tests button
Context ctx = instrumentation.getContext();
Intent intent = new Intent(ctx, StopperActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP); // android:launchMode="singleTop" doesn't work in old versions
intent.putExtra(StopperActivity.PARAM_KILL, true);
ctx.startActivity(intent);
}
}
==> ./src/org/foo/StopperActivity.java <==
...
public class StopperActivity extends Activity {
public static final String ACTION = StopperActivity.class.getName() + ".ACTION";
public static final String PARAM_TEST_NAME = "testName";
public static final String PARAM_KILL = "kill";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stopper);
findViewById(R.id.stop_button).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View view) {
stopTest();
}
});
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
displayTestName(extras);
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Bundle extras = intent.getExtras();
if (extras != null) {
if (extras.containsKey(PARAM_KILL)) {
finish();
} else {
displayTestName(extras);
}
}
}
private void stopTest() {
sendBroadcast(new Intent(ACTION));
finish();
}
private void displayTestName(Bundle extras) {
String testName = extras.getString(PARAM_TEST_NAME);
if (testName == null)
testName = "";
setTitle(testName);
}
}
==> ./res/layout/activity_stopper.xml <==
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="org.foo.StopperActivity" >
<Button
android:id="@+id/stop_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginTop="16dp"
android:paddingLeft="32dp"
android:paddingRight="32dp"
tools:ignore="HardcodedText"
android:text="Stop test" />
</merge>
==> AndroidManifest.xml <==
...
<!-- android:exported="true" - allow launch test activity in context of testee -->
<activity
android:name="org.foo.StopperActivity"
android:exported="true"
android:windowSoftInputMode="adjustResize|stateVisible">
</activity>
...