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.