Уничтожить и перезапустить активность с помощью библиотеки поддержки тестирования
Используя старые тесты в стиле 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());
}
}