Эспрессо и постЗадержка

У меня есть активность, которая использует вызов postDelayed:

public class SplashActivity extends Activity {
    private Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(...);
        handler.postDelayed(new Runnable() { 
            public void run() { finish(); }
        }, 3000L);
    }
 }

Это запускается при запуске приложения, и мне нужно перемещаться по нему и моему экрану входа в систему. Однако loopMainThreadUntilIdle UIController, похоже, не принимает во внимание базовую MessageQueue в обработчике. Таким образом, это действие завершается немедленно, пока в очереди еще есть сообщения.

onView(withId(R.id.splash_screen)).perform(new ViewAction() {
    @Override
    public Matcher<View> getConstraints() {
        return isAssignableFrom(View.class);
    }

    @Override
    public String getDescription() {
        return "";
    }

    @Override
    public void perform(final UiController uiController, final View view) {
        uiController.loopMainThreadUntilIdle();
    }
});

Я не смог понять, как заблокировать, пока очередь не будет исчерпана. Сам Android не позволяет мне делать много вещей, которые я бы попробовал (например, расширение Handler и переопределение метода postDelayed и т. д.).

У кого-нибудь есть предложения о том, как обрабатывать postDelayed?

Я бы предпочел избегать uiController.loopMainThreadForAtLeast, который кажется хакерским (например, Thread.sleep)


person Matt    schedule 21.08.2015    source источник


Ответы (2)


Когда эспрессо ждет, он действительно учитывает MessageQueue, но не так, как вы думаете. Чтобы быть бездействующей, очередь должна быть либо пустой, либо или должна быть запущена задача через более чем 15 миллисекунд.

Вы можете сами проверить код, особенно метод loopUntil() в UiControllerImpl.java и файл QueueInterrogator.java. В последнем файле вы также найдете логику того, как Espresso проверяет MessageQueue (метод determineQueueState()).

Теперь как решить вашу проблему? Есть много способов:

  1. Используйте AsyncTask вместо Handler, спите в фоновом потоке и выполняйте действия onPostExecute(). Это работает, потому что Espresso будет ждать завершения AsyncTask, но вам могут не понравиться накладные расходы другого потока.

  2. Спите в своем тестовом коде, но вам уже не нравится такой подход.

  3. Напишите свой собственный IdlingResource: это общий механизм, позволяющий Espresso знать, когда что-то простаивает, чтобы он мог запускать действия и утверждения. Для этого подхода вы можете:

    • Используйте класс CountingIdlingResource, который поставляется с эспрессо.

    • Вызовите increment(), когда вы публикуете свой runnable, и decrement() внутри runnable после того, как ваша логика будет запущена.

    • Зарегистрируйте свой IdlingResource в тестовой настройке и отмените его регистрацию в демонтаже.

См. также: документы и примеры, другой образец

person Gil Vegliach    schedule 22.08.2015
comment
Я думаю, что могу просто абстрагироваться от помещения сообщения в очередь и внедрить какую-то другую реализацию, которая действует как IdlingResource. У меня будет реализация по умолчанию в моем коде, которая зависит от обработчика, а в тестовом коде - IdlingResource и icnrements/decrements - person Matt; 22.08.2015

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

Вы бы в основном опрашивали свое состояние каждые x мс, что-то вроде.

while (!conditionIsMet() && currentTime < timeOut){
    sleep(100);
}

boolean conditionIsMet() {
    return "espresso check for if your splash view exists";
}
person JohanShogun    schedule 21.08.2015
comment
Проблема в том, что Android не дает вам возможности действительно заглянуть в очередь сообщений, чтобы увидеть, не стоит ли что-нибудь в очереди. Это должно быть что-то, что было перехвачено и заменено во время запуска (что, я думаю, и делает роботиум). - person Matt; 21.08.2015
comment
Класс waitForCondition просто опрашивает условие, которое вы пишете сами. Что касается роботиума, проверяющего очередь, я в это не верю, я тоже видел такие проблемы, как у вас, с роботиумом. - person JohanShogun; 21.08.2015
comment
Для этого варианта использования вы должны иметь возможность дождаться выполнения действия вместо того, чтобы смотреть в очередь сообщений (что действительно более интересно с точки зрения тестирования). - person JohanShogun; 21.08.2015