Уничтожить и перезапустить активность с помощью библиотеки поддержки тестирования

Используя старые тесты в стиле JUnit3 в Android, я мог сделать следующее, чтобы уничтожить и перезапустить действие:

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 ответа

Как упомянул @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(),

Как говорят 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());
  }
}

Ответ 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... */ }

Попробуйте создать собственное правило. Вызов 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());
    }
}
Другие вопросы по тегам