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
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!
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
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
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.
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.