5

次のアクティビティがあります。

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()ですか?

4

2 に答える 2

6

問題の現在のアクティビティの実装では、つまり、ChildActivity のボタンをクリックして結果を設定し、すぐにアクティビティを破棄すると、結果関連のものをテストするために 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");
  }

  ... ...
}

ここに 3 つの Thread.sleep() 呼び出しを追加して、JUnit テストの実行時にボタン クリックのシミュレーションを確認できるようにします。ここでわかるように、スタンドアロンの ChildActivityTest は連携全体をテストするには不十分です。最初から相互作用全体をシミュレートする必要があるため、実際には MainActivityTest を介して間接的に ChildActivity.setResult() をテストしています。

于 2012-10-28T21:21:20.337 に答える
1

Robotium フレームワークの使用をお勧めします。Robotium は、非常に役立つ API を持つクラス Solo を使用します。

これにより、現在のアクティビティが何であるかを確認できます。アクティビティが開始されたことなどをアサートできます。

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 は、同じアプリケーション内のアクティビティに対してのみ機能します。

于 2012-10-24T01:56:00.433 に答える