10

在 Android 中使用旧的 JUnit3 样式测试,我可以执行以下操作来破坏和重新启动活动:

Instrumentation inst = getInstrumentation();
Activity activity = inst.getActivity();
// do something
activity.finish();
Assert.assertTrue(this.activity.isFinishing());
activity = inst.getActivity();
// assert that activity's state is restored

如何使用新的测试支持库完成同样的事情?我可以使用 Espresso 和/或 UI Automator 或新库提供的任何其他机制。

更新:

我尝试了以下方法:

Activity activity = activityTestRule.getActivity();
// do something
activity.finish();
Assert.assertTrue(this.activity.isFinishing());
activity = activityTestRule.getActivity();
// assert that activity's state is restored

但是,似乎ActivityTestRule.getActivity()不会重新启动活动。

4

4 回答 4

7

正如@CommonsWare 提到的,自定义规则非常有用。这是我的简单解决方案(可以进行许多改进,但这只是一个可以构建的快速框架):

public class ControlledActivityTestRule<T extends Activity> extends ActivityTestRule<T> {
    public ControlledActivityTestRule(Class<T> activityClass) {
        super(activityClass, false);
    }

    public ControlledActivityTestRule(Class<T> activityClass, boolean initialTouchMode) {
        super(activityClass, initialTouchMode, true);
    }

    public ControlledActivityTestRule(Class<T> activityClass, boolean initialTouchMode, boolean launchActivity) {
        super(activityClass, initialTouchMode, launchActivity);
    }

    public void finish() {
        finishActivity();
    }

    public void relaunchActivity() {
        finishActivity();
        launchActivity();
    }

    public void launchActivity() {
        launchActivity(getActivityIntent());
    }
}

注意,如果你这样做,这个类需要在包android.support.test.rule中才能访问包私有方法ActivityTestRule#finishActivity。然后在你的测试用例中,实现这个规则:

@Rule
public ControlledActivityTestRule<TestFountainPreferenceActivity> actRule = new ControlledActivityTestRule<>(TestFountainPreferenceActivity.class);

然后在您的个人测试用例中,调用actRule.finish()actRule.launchActivity()杀死并重新启动它。或者,actRule.relaunchActivity()如果您在杀死它和重新启动它之间不需要做任何事情,您可以打电话。注意,如果你有初始启动,你可以传递第三个参数false来延迟启动活动,然后调用actRule.launchActivity()它来启动它,但是你将失去对一些内置句柄的访问权限,例如#afterActivityLaunched#afterActivityFinished()

于 2016-04-21T19:41:35.310 回答
2

正如 JCricket 和 djunod 所说,这样做的方法是创建自定义规则。我在他们的解决方案中遇到的问题是方法 finishActivity 是包保护的,您可以在自定义测试规则中使用它。

这是我的解决方案:

public class RelaunchActivityRule<T extends Activity> extends ActivityTestRule<T> {

  public RelaunchActivityRule(Class<T> activityClass) {
    super(activityClass,false);
  }

  public RelaunchActivityRule(Class<T> activityClass, boolean initialTouchMode) {
    super(activityClass, initialTouchMode,true);
  }

  public RelaunchActivityRule(Class<T> activityClass, boolean initialTouchMode,
      boolean launchActivity) {
    super(activityClass, initialTouchMode, launchActivity);
  }

  @Override protected void afterActivityFinished() {
    super.afterActivityFinished();
    launchActivity(getActivityIntent());
  }
}
于 2017-05-25T07:21:06.393 回答
0

尝试创建自定义规则。调用方法launchActivity(getActivityIntent())afterActivityFinished完成后将重新启动活动。

public class RestartActivityRule<T extends Activity> extends ActivityTestRule<T> {

    public RestartActivityRule(Class<T> activityClass) {
        super(activityClass,false);
    }

    public RestartActivityRule(Class<T> activityClass, boolean initialTouchMode) {
        super(activityClass, initialTouchMode,true);
    }

    public RestartActivityRule(Class<T> activityClass, boolean initialTouchMode,
      boolean launchActivity) {
        super(activityClass, initialTouchMode, launchActivity);
    }

    @Override protected void afterActivityFinished() {
        super.afterActivityFinished();
        launchActivity(getActivityIntent());
    }
}
于 2017-05-25T07:29:13.643 回答
0

一旦我在那里添加了一个睡眠,JCricket 的答案就对我有用......

package android.support.test.rule;

public class ControlledActivityTestRule<T extends Activity> extends ActivityTestRule<T> {
    public ControlledActivityTestRule(Class<T> activityClass) {
        super(activityClass, false);
    }

    public ControlledActivityTestRule(Class<T> activityClass, boolean initialTouchMode) {
        super(activityClass, initialTouchMode, true);
    }

    public ControlledActivityTestRule(Class<T> activityClass, boolean initialTouchMode, boolean launchActivity) {
        super(activityClass, initialTouchMode, launchActivity);
    }

    public void finish() {
        finishActivity();
    }

    public void relaunchActivity(int seconds) {
        finishActivity();
        sleep(seconds);
        launchActivity();
        sleep(seconds);
    }

    public void launchActivity() {
        launchActivity(getActivityIntent());
    }

    public void sleep(int seconds) {
        if (seconds > 0) {
            try {
                Thread.sleep(seconds * 1000);
            } catch (Exception ex) {
            }
        }
    }
}

然后,我能够通过迭代进行测试:

@Rule
public ControlledActivityTestRule<MainActivity> mActivityRule = new ControlledActivityTestRule<>(MainActivity.class);

@Test
public void testOAA310() {
    int count = 1000;
    for (int i = 0; i < count; i++) {
        testCaseOAA310();
        mActivityRule.relaunchActivity(5);
    }
}

void testCaseOAA310() { /* ... blah blah blah... */ }
于 2016-11-14T11:08:34.603 回答