Instrumentation test for Android - How to receive new Activity after orientation change?

后端 未结 5 803
臣服心动
臣服心动 2021-01-06 04:11


I\'m trying to test, if newly created Activity (after orientation change) is properly reinitialized. The code below shows that activity returned from getActivity() is t

相关标签:
5条回答
  • 2021-01-06 04:42

    Ok, I think I finally managed to solve it - with robotium framework. I'm attaching the solution in case someone had the same problem.

    Test:

    public class MyActivityTest extends ActivityInstrumentationTestCase2<MyActivity>{
    
    private static final String TAG = "RAMPS";
    private MyActivity mActivity;
    private Solo mSolo;
    
    public MyActivityTest() {
        super("com.ramps", MyActivity.class);
    
    }
    
    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mActivity = getActivity();
        mSolo = new Solo(getInstrumentation(), getActivity());
        Log.v(TAG, "setUp; activity=" + mActivity);
    }
    
    public void testOrienationChange(){     
        mSolo.setActivityOrientation(Solo.LANDSCAPE);
        getInstrumentation().waitForIdleSync();
        MyActivity newActivity = getActivity(); //should be new, but it's not
        Activity newActivity2 = mSolo.getCurrentActivity(); //this will return new activity
        Log.v(TAG, "testOrienationChange; activity=" + newActivity);
        Log.v(TAG, "testOrienationChange; activity2=" + newActivity2);
    }   
    

    }

    And log messages - for confirmation:

    06-11 18:47:02.631: V/RAMPS(716): onCreate; activity=MyActivity@44c326a8
    06-11 18:47:03.061: V/RAMPS(716): setUp; activity=MyActivity@44c326a8
    06-11 18:47:03.781: V/RAMPS(716): onCreate; activity=MyActivity@44c481e0
    06-11 18:47:04.482: V/RAMPS(716): testOrienationChange; activity=MyActivity@44c326a8
    06-11 18:47:04.482: V/RAMPS(716): testOrienationChange; activity2=MyActivity@44c481e0
    

    As you can see, activity returned from mSolo.getCurrentActivity() is the same that was created after orientation change. I really recommend Robotium - another great piece of code from Jayway!

    0 讨论(0)
  • 2021-01-06 04:44

    Instead of

     MyActivity newActivity = getActivity(); //should be new, but it's not
    

    Try

    MyActivity newActivity = instrumentation.startActivitySync(intent);
    

    I think this method maybe help you

    0 讨论(0)
  • 2021-01-06 04:45

    Took @Smok's answer and updated it to always rotate:

    @SuppressWarnings("unchecked") // it's fine
    public static <T extends Activity> T rotate(ActivityInstrumentationTestCase2<T> testCase) {
        T activity = testCase.getActivity();
        int orientation = activity.getWindowManager().getDefaultDisplay().getRotation();
        int nextOrientation = orientation == Configuration.ORIENTATION_LANDSCAPE ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT : ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
        Instrumentation.ActivityMonitor monitor = new Instrumentation.ActivityMonitor(activity.getClass().getName(), null, false);
        testCase.getInstrumentation().addMonitor(monitor);
        activity.setRequestedOrientation(nextOrientation);
        testCase.getInstrumentation().waitForIdleSync();
        return (T) testCase.getInstrumentation().waitForMonitor(monitor);
    }
    

    This fixes the problem of the orientation returning UNSPECIFIED

    0 讨论(0)
  • 2021-01-06 04:55

    This solved my issue, using only the Android testing framework:

        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        mActivity.finish();
        setActivity(null);
        mActivity = getActivity();
        getInstrumentation().waitForIdleSync();
    

    AFAIK, getActivity() does create a new activity if the current one is null which is done by setting it with setActivity(null). Also, the new activity will have the orientation set by Activity.setRequestedOrientation(int).

    If you need to check whether the state is being correctly saved when orientation changes, you should call getInstrumentation().callActivityOnCreate(mActivity, Bundle) from the UI thread.

    0 讨论(0)
  • 2021-01-06 05:02

    I've had the same problem in my UI tests. I don't use Robotium, but I created a new base test class with getActivity() that always returns current activity. The idea is to add an ActivityMonitor before orientation change and just update current activity on monitor wait:

    public class UiTest<T extends Activity> extends ActivityInstrumentationTestCase2<T> {
    
    private final Class<T> activityClass;
    protected T activity;
    
    public UiTest(Class<T> activityClass) {
      super(activityClass);
      this.activityClass = activityClass;
    }
    
    @Override
    protected void setUp() throws Exception {
      super.setUp();
      setActivityInitialTouchMode(false);  // Depends on your needs.
      activity = super.getActivity();
      activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }
    
    /**
     * Rotates the test device and updates current activity.
     */
    protected final void rotate() {
      int nextOrientation =
          activity.getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
              ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
              : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
      Instrumentation.ActivityMonitor monitor =
          new Instrumentation.ActivityMonitor(activityClass.getName(), null, false);
      getInstrumentation().addMonitor(monitor);
      activity.setRequestedOrientation(nextOrientation);
      getInstrumentation().waitForIdleSync();
      this.activity = (T) getInstrumentation().waitForMonitor(monitor);
    }
    
    @Override
    public T getActivity() {
      return activity;
    }
    

    Of course this won't work if activity class changes during the test or if orientation changes by other means, not with rotate() method. I hope this helps somebody.

    0 讨论(0)
提交回复
热议问题