Инструментарий тест для Android - Как получить новую активность после изменения ориентации?
Я пытаюсь проверить, правильно ли инициализирована вновь созданная активность (после изменения ориентации). Приведенный ниже код показывает, что активность, возвращаемая из getActivity (), - это функция, созданная в setUp(), а не вновь созданная.
Тестовое задание:
public class MyActivityTest extends ActivityInstrumentationTestCase2<MyActivity>{
private static final String TAG = "RAMPS";
private MyActivity mActivity;
public MyActivityTest() {
super("com.ramps", MyActivity.class);
}
protected void setUp() throws Exception {
super.setUp();
mActivity = getActivity();
Log.v(TAG, "setUp; activity=" + mActivity);
}
public void testOrienationChange(){
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
getInstrumentation().waitForIdleSync();
MyActivity newActivity = getActivity(); //should be new, but it's not
Log.v(TAG, "testOrienationChange; activity=" + newActivity);
}
}
Activiy:
public class MyActivity extends Activity {
private static final String TAG = "RAMPS";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v(TAG, "onCreate; activity=" + this);
setContentView(new TextView(this));
}
//...rest of stuff like onSaveInstanceState() etc.
}
И журналы:
06-11 14:16:52.431: V/RAMPS(367): onCreate; activity=MyActivity@44eb8690
06-11 14:16:52.891: V/RAMPS(367): setUp; activity=MyActivity@44eb8690
06-11 14:16:52.971: V/RAMPS(367): onCreate; activity=MyActivity@44ee5178
06-11 14:16:53.131: V/RAMPS(367): testOrienationChange; activity=MyActivity@44eb8690
Как упоминалось ранее, журналы показывают, что новое действие действительно создано (MyActivity@44ee5178), но getActivity () возвращает старое действие, созданное в setUp() (MyActivity@44eb8690). Можно ли получить доступ к вновь созданному?
5 ответов
Ладно, думаю, мне наконец удалось решить эту проблему - с помощью фреймворка robotium. Я прилагаю решение на случай, если у кого-то возникла такая же проблема.
Тестовое задание:
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);
}
}
И журнал сообщений - для подтверждения:
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
Как вы можете видеть, активность, возвращаемая из mSolo.getCurrentActivity(), та же, что была создана после изменения ориентации. Я действительно рекомендую Robotium - еще один замечательный кусок кода от Jayway!
У меня была такая же проблема в моих тестах пользовательского интерфейса. Я не использую Robotium, но я создал новый базовый тестовый класс с getActivity()
это всегда возвращает текущую активность. Идея состоит в том, чтобы добавить ActivityMonitor
перед изменением ориентации и просто обновите текущую активность на мониторе:
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;
}
Конечно, это не будет работать, если класс активности изменяется во время теста или если ориентация изменяется другими способами, а не с rotate()
метод. Надеюсь, это кому-нибудь поможет.
Вместо
MyActivity newActivity = getActivity(); //should be new, but it's not
Пытаться
MyActivity newActivity = instrumentation.startActivitySync(intent);
Я думаю, что этот метод может помочь вам
Это решило мою проблему, используя только среду тестирования Android:
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
mActivity.finish();
setActivity(null);
mActivity = getActivity();
getInstrumentation().waitForIdleSync();
НАСКОЛЬКО МНЕ ИЗВЕСТНО, getActivity()
действительно создает новую активность, если текущая является нулевой, что делается путем установки его с setActivity(null)
, Кроме того, новое действие будет иметь ориентацию, установленную Activity.setRequestedOrientation(int)
,
Если вам нужно проверить, правильно ли сохраняется состояние при изменении ориентации, вам следует позвонить getInstrumentation().callActivityOnCreate(mActivity, Bundle)
из потока пользовательского интерфейса.
Взял ответ @Smok и обновил его, чтобы он всегда вращался:
@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);
}
Это решает проблему возврата ориентации UNSPECIFIED