Задержка теста в Espresso Android без зависания основного потока - PullRequest
0 голосов
/ 15 октября 2018

Я новичок в среде тестирования эспрессо.Теперь у меня есть задача протестировать какое-то приложение, которое работает с асинхронным бэкэндом.Пока начинается первое действие, некоторые фрагменты появляются только после загрузки.Это может занять несколько секунд, поэтому проще всего подождать 5-7 секунд.Однако использование IdlingResource останавливает основной поток, поэтому мои внутренние данные не могут загружаться, пока не истечет время ожидания.

Вот как я использую IdlingResource:

public static class ElapsedTimeIdlingResource implements IdlingResource {
    private final long startTime;
    private final long waitingTime;
    private ResourceCallback resourceCallback;

    ElapsedTimeIdlingResource(long waitingTime) {
        this.startTime = System.currentTimeMillis();
        this.waitingTime = waitingTime;
    }

    @Override
    public String getName() {
        return ElapsedTimeIdlingResource.class.getName() + ":" + waitingTime;
    }

    @Override
    public boolean isIdleNow() {
        long elapsed = System.currentTimeMillis() - startTime;
        boolean idle = (elapsed >= waitingTime);
        if (idle) resourceCallback.onTransitionToIdle();
        return idle;
    }

    @Override
    public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
        this.resourceCallback = resourceCallback;
    }
}

Вот как я его называю:

    long waitingTime = 5000;

    onView(withId(R.id.row_content)).check(matches(isDisplayed())).perform(click());

    IdlingPolicies.setMasterPolicyTimeout(waitingTime * 2, TimeUnit.MILLISECONDS);
    IdlingPolicies.setIdlingResourceTimeout(waitingTime * 2, TimeUnit.MILLISECONDS);

    IdlingResource idlingResource = new ElapsedTimeIdlingResource(waitingTime);
    IdlingRegistry.getInstance().register(idlingResource);

   // .... do some tests

   IdlingRegistry.getInstance().unregister(idlingResource);

Как отложить выполнение теста, не блокируя основной поток?

1 Ответ

0 голосов
/ 16 октября 2018

Вам не нужен IdlingResource, если вы просто хотите подождать некоторое время:

public static ViewAction waitFor(long delay) {
    return new ViewAction() {
        @Override public Matcher<View> getConstraints() {
            return ViewMatchers.isRoot();
        }

        @Override public String getDescription() {
            return "wait for " + delay + "milliseconds";
        }

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

И использовать его:

onView(withId(R.id.row_content)).check(matches(isDisplayed())).perform(click());   
onView(isRoot()).perform(waitFor(5000);

Но если вы знаетепредставление появится через некоторое время, затем вы можете использовать IdlingResource, например:

public static ViewAction waitUntil(Matcher<View> matcher) {
    return actionWithAssertions(new ViewAction() {
        @Override public Matcher<View> getConstraints() {
            return ViewMatchers.isAssignableFrom(View.class);
        }

        @Override public String getDescription() {
            StringDescription description = new StringDescription();
            matcher.describeTo(description);
            return String.format("wait until: %s", description);
        }

        @Override public void perform(UiController uiController, View view) {
            if (!matcher.matches(view)) {
                LayoutChangeCallback callback = new LayoutChangeCallback(matcher);
                try {
                    IdlingRegistry.getInstance().register(callback);
                    view.addOnLayoutChangeListener(callback);
                    uiController.loopMainThreadUntilIdle();
                } finally {
                    view.removeOnLayoutChangeListener(callback);
                    IdlingRegistry.getInstance().unregister(callback);
                }
            }
        }
    });
}

private static class LayoutChangeCallback implements IdlingResource, View.OnLayoutChangeListener {

    private Matcher<View> matcher;
    private IdlingResource.ResourceCallback callback;
    private boolean matched = false;

    LayoutChangeCallback(Matcher<View> matcher) {
        this.matcher = matcher;
    }

    @Override public String getName() {
        return "Layout change callback";
    }

    @Override public boolean isIdleNow() {
        return matched;
    }

    @Override public void registerIdleTransitionCallback(ResourceCallback callback) {
        this.callback = callback;
    }

    @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
        matched = matcher.matches(v);
        callback.onTransitionToIdle();
    }
}

и использовать его, например:

onView(withId(R.id.row_content)).check(matches(isDisplayed())).perform(click());
onView(withId(R.id.main_content)).perform(waitUntil(isDisplayed()))
...