Espresso等待textview

时间:2016-05-09 09:42:42

标签: android socket.io android-espresso

我有一个连接到Socket.IO服务器的服务。它是一个发送消息的简单应用程序,它会回显给客户端。我有一个测试如下:

@Test
public void checkSendMessage() {

    final String testMessage = "Here is a test message";

    onView(withId(R.id.textEntry)).perform(typeText(testMessage), closeSoftKeyboard());
    onView(withId(R.id.send)).perform(click());
    onView(withId(R.id.messages)).check(matches(withText(containsString(testMessage))));
}

我在本地网络上运行服务器,在这种情况下,所有内容都会运行并通过。但是,如果我在服务器中添加3秒延迟,则测试失败。我想基本上说等待最多X秒,然后检查它是否包含文本。

我在回答使用IdlingResource时遇到了类似的问题。但是我不确定如何将其集成到我的应用程序中。我想我必须实现isIdleNow函数。我正在使用连接到com.koushikdutta.async.http.socketio.SocketIOClient;

的服务

它永远不会闲置,它只是坐在那里听插座。所以我并不是在等待完成某些事情,我只想继续检查视图最多X秒,看看是否有消息到达。我怎么能这样做?

1 个答案:

答案 0 :(得分:5)

我已经通过编写自定义IdlingResource来解决它,该自定义IdlingResource检查每个isIdleNow上的视图断言,并最终按照以下代码超时:

@Test
public void checkSendMessage() {

    final String testMessage = "Here is a test message";

    onView(withId(R.id.textEntry)).perform(typeText(testMessage), closeSoftKeyboard());
    onView(withId(R.id.send)).perform(click());

    waitFor(onView(withId(R.id.messages)), matches(withText(containsString(testMessage))), 5000);
}

private void waitFor(ViewInteraction viewInteraction, ViewAssertion viewAssertion, long timeout) {

    PollingTimeoutIdler idler = new PollingTimeoutIdler(viewInteraction, viewAssertion, timeout);
    Espresso.registerIdlingResources(idler);

    viewInteraction.check(viewAssertion);

    Espresso.unregisterIdlingResources(idler);
}

private class PollingTimeoutIdler implements IdlingResource {

    private final ViewAssertion mViewAssertion;
    private final long mTimeout;
    private final long mStartTime;
    private ResourceCallback mCallback;
    private volatile View mTestView;

    public PollingTimeoutIdler(ViewInteraction viewInteraction, ViewAssertion viewAssertion, long timeout) {
        mViewAssertion = viewAssertion;
        mTimeout = timeout;
        mStartTime = System.currentTimeMillis();

        viewInteraction.check(new ViewAssertion() {
            @Override
            public void check(View view, NoMatchingViewException noViewFoundException) {
                mTestView = view;
            }
        });
    }

    @Override
    public String getName() {
        return getClass().getSimpleName();
    }

    @Override
    public boolean isIdleNow() {

        long elapsed = System.currentTimeMillis() - mStartTime;
        boolean timedOut = elapsed >= mTimeout;

        boolean idle = testView() || timedOut;
        if(idle) {
            mCallback.onTransitionToIdle();
        }

        return idle;
    }

    private boolean testView() {

        if(mTestView != null) {
            try {
                mViewAssertion.check(mTestView, null);
                return true;
            }
            catch(AssertionFailedError ex) {
                return false;
            }
        }
        else {
            return false;
        }
    }

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

它有效,但肯定有更好的方法吗?这感觉超级hacky和Espresso应该提供给我的东西。事实上,它并没有让我相信我正在考虑这个测试的错误方法。有没有更好的方法来测试相同的行为?