Android仪器测试-如何在方向改变后接收新活动?

Android仪器测试-如何在方向改变后接收新活动?,android,unit-testing,instrumentation,android-testing,Android,Unit Testing,Instrumentation,Android Testing,我试图测试新创建的活动(方向更改后)是否正确地重新初始化。下面的代码显示从getActivity()返回的活动是在setUp()中构造的活动,而不是新创建的活动 测试: public class MyActivityTest extends ActivityInstrumentationTestCase2<MyActivity>{ private static final String TAG = "RAMPS"; private MyActivity mActivity;


我试图测试新创建的活动(方向更改后)是否正确地重新初始化。下面的代码显示从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);       
 }
}

和日志:

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). 有可能访问新创建的一个吗?

好的,我想我终于用框架解决了这个问题。我正在附上解决方案,以防有人遇到同样的问题。

测试:

如您所见,从mSolo.getCurrentActivity()返回的活动与方向更改后创建的活动相同。我真的推荐Robotium——另一段来自Jayway的伟大代码

而不是

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


我想这个方法可能会帮助你

我在UI测试中也遇到过同样的问题。我不使用Robotium,但我使用
getActivity()
创建了一个新的基本测试类,它总是返回当前活动。我们的想法是在方向更改之前添加一个
活动监视器
,只需在监视器等待时更新当前活动:

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;
}
公共类UiTest扩展了ActivityInstrumentationTestCase2{
私人期末班活动班;
保护性T细胞活性;
公共UiTest(类activityClass){
超级(活动类);
this.activityClass=activityClass;
}
@凌驾
受保护的void setUp()引发异常{
super.setUp();
setActivityInitialTouchMode(false);//取决于您的需要。
activity=super.getActivity();
activity.setRequestedOrientation(ActivityInfo.SCREEN\u-ORIENTATION\u-Picture);
}
/**
*旋转测试设备并更新当前活动。
*/
受保护的最终空心旋转(){
内接=
activity.getRequestedOrientation()==ActivityInfo.SCREEN\u方向图
?ActivityInfo.SCREEN\u方向\u横向
:ActivityInfo.SCREEN\u方向\u纵向;
仪器仪表.活动监视器=
新的Instrumentation.ActivityMonitor(activityClass.getName(),null,false);
getInstrumentation().addMonitor(监视器);
activity.setRequestedOrientation(nextOrientation);
getInstrumentation().waitForIdleSync();
this.activity=(T)getInstrumentation().WaitFormMonitor(监视器);
}
@凌驾
公共活动{
返回活动;
}

当然,如果活动类在测试过程中发生变化,或者方向通过其他方式发生变化,而不是使用
rotate()
方法,那么这将不起作用。我希望这对某些人有所帮助。

接受@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);
}
@SuppressWarnings(“未选中”)//很好
公共静态T旋转(ActivityInstrumentationTestCase2测试用例){
T activity=testCase.getActivity();
int-orientation=activity.getWindowManager().getDefaultDisplay().getRotation();
int nextOrientation=方向==配置.ORIENTION\u横向?活动信息.SCREEN\u横向:活动信息.SCREEN\u横向;
Instrumentation.ActivityMonitor监视器=新建Instrumentation.ActivityMonitor(activity.getClass().getName(),null,false);
testCase.getInstrumentation().addMonitor(监视器);
activity.setRequestedOrientation(nextOrientation);
testCase.getInstrumentation().waitForIdleSync();
返回(T)testCase.getInstrumentation().WaitFormMonitor(监视器);
}

这解决了方向返回未指定的问题。这解决了我的问题,仅使用Android测试框架:

    mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    mActivity.finish();
    setActivity(null);
    mActivity = getActivity();
    getInstrumentation().waitForIdleSync();
好的,
getActivity()
如果当前活动为空,则会创建一个新活动,这是通过使用
setActivity(null)
进行设置来完成的。此外,新活动的方向将由
activity.setRequestedOrientation(int)
设置

如果需要检查方向更改时是否正确保存状态,则应从UI线程调用
getInstrumentation().callActivityOnCreate(MacActivity,Bundle)

MyActivity newActivity = instrumentation.startActivitySync(intent);
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;
}
@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);
}
    mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    mActivity.finish();
    setActivity(null);
    mActivity = getActivity();
    getInstrumentation().waitForIdleSync();