Android 测试活动是否返回预期结果

Android 测试活动是否返回预期结果,android,testing,junit,android-activity,instrumentation,Android,Testing,Junit,Android Activity,Instrumentation,我有以下活动: package codeguru.startactivityforresult; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; public class ChildActivity extends Activity { @Overri

我有以下活动:

package codeguru.startactivityforresult;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class ChildActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.child);

        this.resultButton = (Button) this.findViewById(R.id.result_button);
        this.resultButton.setOnClickListener(onResult);
    }

    private View.OnClickListener onResult = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent result = new Intent();
            result.putExtra(ChildActivity.this.getString(R.string.result), ChildActivity.this.getResources().getInteger(R.integer.result));
            ChildActivity.this.setResult(RESULT_OK, result);
            ChildActivity.this.finish();
        }
    };
    private Button resultButton = null;
}
以及以下JUnit测试:

package codeguru.startactivityforresult;

import android.app.Activity;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
import android.widget.Button;
import junit.framework.Assert;

public class ChildActivityTest extends ActivityInstrumentationTestCase2<ChildActivity> {

    public ChildActivityTest() {
        super(ChildActivity.class);
    }

    @Override
    public void setUp() throws Exception {
        super.setUp();

        this.setActivityInitialTouchMode(false);

        this.activity = this.getActivity();
        this.resultButton = (Button) this.activity.findViewById(R.id.result_button);
    }

    @Override
    public void tearDown() throws Exception {
        super.tearDown();
    }

    @UiThreadTest
    public void testResultButtonOnClick() {
        Assert.assertTrue(this.resultButton.performClick());
        Assert.fail("How do I check the returned result?");
    }
    private Activity activity;
    private Button resultButton;
}
package codeguru.startactivityforresult;
导入android.app.Activity;
导入android.test.ActivityInstrumentationTestCase2;
导入android.test.UiThreadTest;
导入android.widget.Button;
导入junit.framework.Assert;
公共类ChildActivityTest扩展了ActivityInstrumentationTestCase2{
公共儿童活动测试(){
super(ChildActivity.class);
}
@凌驾
public void setUp()引发异常{
super.setUp();
此.setActivityInitialTouchMode(false);
this.activity=this.getActivity();
this.resultButton=(按钮)this.activity.findViewById(R.id.result_按钮);
}
@凌驾
public void tearDown()引发异常{
super.tearDown();
}
@超线程测试
public void testResultButtonOnClick(){
Assert.assertTrue(this.resultButton.performClick());
Assert.fail(“如何检查返回的结果?”);
}
私人活动;
私有按钮结果按钮;
}

如何确保单击按钮设置正确的结果(调用
setResult()
),该结果将返回到任何使用
startActivityForResult()
启动此活动的活动?

我建议使用Robotium framework。Robotium使用一个类Solo,它有一个非常有用的API

它允许您查看当前活动是什么。允许您断言活动已启动等

执行单击后,可以执行以下操作

void assertCurrentActivity(java.lang.String消息、java.lang.Class expectedClass、boolean isNewInstance)         这就是我要做的。 输入代码后单击按钮

Activity callingActvity  = solo.getCurrentActivity();
  solo.assertCurrentActivity("ShouldbeCallingActivity","NameOfCallingActivity");
如果不知道回调是如何工作的,我无法给出完整的解决方案。但是假设某个文本显示为RESULT_OK,而不是其他文本

你可以这样做

assertTrue(solo.waitForText("Text that is supposed to show for Result OK");

PS:robotium将仅适用于同一应用程序中的活动。

对于问题中的当前活动实施,即通过单击ChildActivity中的按钮设置结果,然后立即销毁活动,我们在ChildActivityTest中无法做太多与测试结果相关的事情

相关问题中的答案显示了如何在MainActivityTest中对startActivityForResult()和/或onActivityResult()独立进行单元测试。通过独立方式,MainActivityTest不依赖于ChildActivity的交互,检测将捕获ChildActivity创建并立即终止它,然后返回一个现成的模拟ActivityResult,因此,单元测试MainActivity

如果不希望检测中断并返回模拟ActivityResult,可以让ChildActivity继续运行,然后模拟ChildActivity中的交互,并将真实ActivityResult返回到MainActivity。表示如果您为结果维护Activity start ChildActivity,然后更新文本视图,要测试整个端到端交互/协作,请参阅下面的示例代码:

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
  ... ...

  public void testStartActivityForResult() {
    MainActivity mainActivity = getActivity();
    assertNotNull(activity);

    // Check initial value in TextView:
    TextView text = (TextView) mainActivity.findViewById(com.example.R.id.textview1);
    assertEquals(text.getText(), "default vaule");

    try {
      Thread.sleep(2000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    // Create an ActivityMonitor that monitor ChildActivity, do not interrupt, do not return mock result:
    Instrumentation.ActivityMonitor activityMonitor = getInstrumentation().addMonitor(ChildActivity.class.getName(), null , false);

    // Simulate a button click in MainActivity that start ChildActivity for result:
    final Button button = (Button) mainActivity.findViewById(com.example.R.id.button1);
    mainActivity.runOnUiThread(new Runnable() {
      public void run() {
        button.performClick();
      }
    });

    try {
      Thread.sleep(2000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    getInstrumentation().waitForIdleSync();
    ChildActivity childActivity = (ChildActivity) getInstrumentation().waitForMonitorWithTimeout(activityMonitor, 5);
    // ChildActivity is created and gain focus on screen:
    assertNotNull(childActivity);

    // Simulate a button click in ChildActivity that set result and finish ChildActivity:
    final Button button2 = (Button) childActivity.findViewById(com.example.R.id.button1);
    childActivity.runOnUiThread(new Runnable() {
      public void run() {
        button2.performClick();
      }
    });

    try {
      Thread.sleep(2000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    getInstrumentation().waitForIdleSync();
    // TextView in MainActivity should be changed:
    assertEquals(text.getText(), "default value changed");
  }

  ... ...
}
公共类MainActivityTest扩展ActivityInstrumentationTestCase2{
... ...
公共无效测试StartActivityForresult(){
MainActivity MainActivity=getActivity();
assertNotNull(活动);
//检查TextView中的初始值:
TextView text=(TextView)mainActivity.findViewById(com.example.R.id.textview1);
assertEquals(text.getText(),“默认值”);
试一试{
《睡眠》(2000年);
}捕捉(中断异常e){
e、 printStackTrace();
}
//创建一个ActivityMonitor,用于监视子活动、不中断、不返回模拟结果:
Instrumentation.ActivityMonitor ActivityMonitor=getInstrumentation().addMonitor(ChildActivity.class.getName(),null,false);
//模拟在MainActivity中单击按钮以启动ChildActivity以获得结果:
final Button Button=(Button)mainActivity.findViewById(com.example.R.id.button1);
mainActivity.runOnUiThread(新的Runnable(){
公开募捐{
button.performClick();
}
});
试一试{
《睡眠》(2000年);
}捕捉(中断异常e){
e、 printStackTrace();
}
getInstrumentation().waitForIdleSync();
ChildActivity ChildActivity=(ChildActivity)getInstrumentation().WaitFormMonitorWithTimeout(activityMonitor,5);
//创建儿童活动并在屏幕上获得焦点:
assertNotNull(儿童活动);
//模拟在ChildActivity中单击按钮以设置结果并完成ChildActivity:
final Button button2=(Button)childActivity.findViewById(com.example.R.id.button1);
childActivity.runOnUiThread(新的Runnable(){
公开募捐{
按钮2.performClick();
}
});
试一试{
《睡眠》(2000年);
}捕捉(中断异常e){
e、 printStackTrace();
}
getInstrumentation().waitForIdleSync();
//应更改MainActivity中的TextView:
assertEquals(text.getText(),“默认值已更改”);
}
... ...
}

我在这里添加了三个Thread.sleep()调用,这样您就可以在运行JUnit测试时看到单击模拟按钮。正如您在这里看到的,单独的ChildActivityTest不足以测试整个协作,我们实际上是通过MainActivityTest间接测试ChildActivity.setResult(),因为我们需要从一开始就模拟整个交互。

这仍然不能回答我的问题。正如您在我的代码中看到的,OnClickListener调用
Activity.setResult()
。我想将代码(可能包括断言)添加到JUnit测试中,以检查结果设置为什么。机器人能做到这一点吗?更好的是,我如何使用标准的Android API来实现它呢?所以您不能像断言当前活动是父活动这样做吗。检查结果?这是我的问题。我该怎么做?(我一定会在t