Как остановить и перезапустить действие в тесте инструментария Android?

Я пытаюсь написать инструментальный тест активности Android, который останавливает (onPause(), затем onStop()) и перезапускает текущее действие. Я пытался

activity.finish();
activity = getActivity();

... но, похоже, это не работает должным образом.

Цель теста - подтвердить, что данные формы сохраняются во время метода onPause() и повторно считываются во время метода onStart(). Это работает, если делать это вручную, но тест не проходит, из чего я делаю вывод, что activity.finish() кажется неправильным способом остановить и перезапустить действие.


Изменить: Моя основная проблема, похоже, связана с синхронизацией. После перезапуска активности исполнитель тестов не ждал, пока завершатся все обработчики событий. Следующая строка останавливает выполнение теста до тех пор, пока действие не станет незанятым:

getInstrumentation().waitForIdleSync()

Кроме того, взгляните на принятый ответ, чтобы получить более ценную информацию о жизненном цикле.


person Danilo Bargen    schedule 24.04.2012    source источник
comment
Что именно не работает должным образом?   -  person yorkw    schedule 24.04.2012
comment
@yorkw Я обновил вопрос, спасибо за комментарий.   -  person Danilo Bargen    schedule 24.04.2012
comment
Что вы имеете в виду, когда говорите, делать это вручную?   -  person Joel Skrepnek    schedule 24.04.2012
comment
@JoelSkrepnek Есть флажок, который включает и отключает эту функцию. Когда я снимаю флажок, закрываю и снова открываю приложение, все данные исчезают. Когда я проверяю его и закрываю или убиваю, а затем снова открываю приложение, все данные формы восстанавливаются.   -  person Danilo Bargen    schedule 24.04.2012


Ответы (5)


Вызов (или вызов изменения ориентации экрана):

activity.finish(); // old activity instance is destroyed and shut down.
activity = getActivity(); // new activity instance is launched and created.

Вызывающие активность проходят полный жизненный цикл отдыха:

onPause() -> onStop() -> onDestroy() -> onCreate()

Что вам нужно:

onPause() -> onStop() -> onRestart()

Недавно я представил Instrumentation API и обнаружил множество интересных триггеров жизненного цикла активности. метод callActivityOnXXX (), следующая единственная строка кода должна помочь:

MyActivity myActivity = getActivity();
// make activity falling into restart phase:
getInstrumentation().callActivityOnRestart(myActivity);

Цитата из диаграммы жизненного цикла активности из официального руководства для разработчиков: введите описание изображения здесь

person yorkw    schedule 24.04.2012
comment
На самом деле, я уже попробовал первое решение, и оно, похоже, не сработало, как вы можете видеть в моем вопросе. Но, возможно, вы правы, и проблема не связана ... Повторите ваше второе предложение, я попробую его позже ... - person Danilo Bargen; 25.04.2012
comment
что на самом деле сработало, большое спасибо! :) не могли бы вы поместить это в начало своего ответа, чтобы другим было легче найти? - person Danilo Bargen; 04.05.2012
comment
Спасибо за редактирование. И последнее замечание: у меня тоже были проблемы с синхронизацией. Тест не ждал завершения обработчика событий жизненного цикла. Помогло добавление getInstrumentation().waitForIdleSync() после перезапуска активности. - person Danilo Bargen; 04.05.2012
comment
Действительно ли getInstrumentation (). CallActivityOnRestart (myActivity) приводит к onPause () - ›onStop () -› onRestart ()? Я пробовал, и это не так. - person Eugene; 12.02.2013
comment
@siik, без подробностей и расследования сложно сказать. Мой первый снимок - убедиться, что callActivityOnRestart () вызывается из основного потока приложения (или потока пользовательского интерфейса), т.е. в случае использования аннотации @UiThreadTest обернуть все тело тестового метода. - person yorkw; 13.02.2013

Я попытался вызвать .finish (), setActivity (null), getActivity (), и он перезапустил действие, но для меня это не восстанавливало состояние. Я попробовал все другие ответы на SO и все другие методы, которые я мог найти в Интернете, и ни один из них не работал у меня. После долгих экспериментов я обнаружил следующие работы (nb: требуется уровень API 11+):

    getInstrumentation().runOnMainSync(new Runnable() {
        @Override
        public void run() {
            activity.recreate();
        }
    });
    setActivity(null);
    activity = getActivity();

Когда я это делаю, создается новый экземпляр Activity, а также создается новый экземпляр фрагмента, который я прикрепил к действию ранее в тесте, и действие и фрагмент восстанавливают свое состояние ожидаемым образом.

Я не знаю, как это работает или почему это работает, я пришел к этому решению методом проб и ошибок, и я тестировал его только на Nexus 4 с KitKat. Я не могу гарантировать, что он правильно имитирует активный отдых, но он работал для моих целей.

Изменить: позже я понял, как это работает. getActivity () работает через регистрацию хуков, которые получают новые создаваемые Activity, которые перехватывают новое Activity, созданное activity.recreate (). setActivity(null) требовалось очистить внутренний кеш, поддерживающий getActivity, иначе он вернет старый и не будет искать новый.

Вы можете увидеть, как это работает, изучив исходный код для различных классов тестовых примеров, из которых они происходят.

person ZoFreX    schedule 14.01.2014

Хороший способ тестирования событий жизненного цикла - изменение ориентации экрана. По моему опыту, это удобный способ обезопасить шаблон onPause / onStart.

person Joel Skrepnek    schedule 24.04.2012
comment
Интересная идея. Проблема заключается в том, что Android по умолчанию сохраняет данные формы при изменении ориентации экрана, так что это не покрывает этот тестовый пример ... - person Danilo Bargen; 24.04.2012
comment
Изменение ориентации экрана приводит к завершению жизненного цикла действия: ... - ›onPause () -› onStop () - ›onDestroy () -› onCreate () - ›onStart () -› ..., который имеет то же поведение, что и вызов activity.finish (); активность = getActivity (); - person yorkw; 24.04.2012
comment
@DaniloBargen Я не верю, что данные формы сохраняются по умолчанию при уничтожении действия. - person Joel Skrepnek; 24.04.2012
comment
@JoelSkrepnek Я тестировал его на своем устройстве ICS. завершение или закрытие приложения приводит к появлению пустого поля формы. При изменении ориентации экрана все данные формы сохраняются. - person Danilo Bargen; 24.04.2012

Может быть, вы могли бы попытаться сохранить имя своего действия, завершить его ... и использовать отражение, чтобы получить новый экземпляр .class для нового намерения создать ...

person Thkru    schedule 24.04.2012

Измените свой код следующим образом:

mActivity.finish();
    setActivity(null);
    mActivity = this.getActivity();

В этом вопросе можно найти полное объяснение

person Padi    schedule 22.01.2013