[英]How do you force an orientation change in an Android Instrumentation test?
[英]Instrumentation test for Android - How to receive new Activity after orientation change?
我正在嘗試測試,如果新創建的Activity(在方向更改后)正確地重新初始化。 下面的代碼顯示從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)中創建的舊活動。 是否可以訪問新創建的?
好吧,我想我終於設法解決了它 - 使用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的另一個很棒的代碼!
我的UI測試中遇到了同樣的問題。 我不使用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);
我認為這種方法可能對你有幫助
取了@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
的方向問題
這解決了我的問題,僅使用Android測試框架:
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
mActivity.finish();
setActivity(null);
mActivity = getActivity();
getInstrumentation().waitForIdleSync();
AFAIK, getActivity()
確實創建了一個新活動,如果當前的活動為null,則通過使用setActivity(null)
設置它。 此外,新活動將具有Activity.setRequestedOrientation(int)
設置的方向。
如果需要檢查方向更改時是否正確保存狀態,則應從UI線程調用getInstrumentation().callActivityOnCreate(mActivity, Bundle)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.