【问题标题】:Testing that an Activity returns the expected result测试 Activity 是否返回预期结果
【发布时间】:2012-10-24 01:49:43
【问题描述】:

我有以下活动:

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

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

【问题讨论】:

  • Testing onActivityResult() 的可能重复项
  • @JohnB 这是一个相关但完全不同的问题。在这里,我问如何测试“孩子”活动。您作为可能重复提供的问题询问有关测试“父”活动的问题。我决定将它们作为两个单独的问题发布,以便我可以提出两个重点问题,而不是将这两个问题隐藏在大量代码之间。

标签: android testing junit android-activity instrumentation


【解决方案1】:

在问题中使用当前的 Activity 实现,即通过单击 ChildActivity 中的按钮设置结果然后立即销毁 Activity,我们在 ChildActivityTest 中对测试结果相关的东西无能为力。

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

如果您不希望检测中断并返回模拟的ActivityResult,您可以让ChildActivity 继续运行,然后模拟ChildActivity 中的交互,并将真实的ActivityResult 返回给MainActivity。表示如果 MainActivity 启动 ChildActivity 以获得结果然后更新 TextView,以测试整个端到端交互/协作,请参见下面的示例代码:

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");
  }

  ... ...
}

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

【讨论】:

【解决方案2】:

我可以推荐使用 Robotium 框架。 Robotium 使用了一个类 Solo,它有一个非常有用的 API。

它允许您查看当前活动是什么。允许您断言某个活动已开始等。

http://code.google.com/p/robotium/

执行点击后,您可以执行类似的操作

 void assertCurrentActivity(java.lang.String message, 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 仅适用于同一应用程序中的活动。

【讨论】:

  • 这仍然没有回答我的问题。正如您在我的代码中看到的,OnClickListener 调用Activity.setResult()。我想在我的 JUnit 测试中添加代码(可能包括断言)以检查结果的设置。 Robotium会这样做吗?更好的是,如何使用标准的 Android API 做到这一点?
  • 所以你不能做一些类似断言当前活动是父活动的事情。并检查结果?
  • 这是我的问题。我怎么做? (我肯定会在不久的将来研究robotium。我刚刚开始进行Android测试——大约一周前——所以我想在查看其他API之前学习如何使用它。)
  • 虽然我很欣赏查看 Robotium 的建议,但这并不能回答我的问题。
  • 这就是我的观点。你的建议并没有把我引向我正在走向的终点。您的回答没有解决有关如何检查通过调用setResult() 存储的结果的主要问题。
猜你喜欢
  • 1970-01-01
  • 2022-01-24
  • 2019-02-26
  • 1970-01-01
  • 2011-08-09
  • 2010-09-22
  • 2021-05-17
  • 2018-02-19
  • 2018-03-23
相关资源
最近更新 更多