【问题标题】:Espresso waiting for textview浓缩咖啡等待文本视图
【发布时间】:2016-05-09 09:42:42
【问题描述】:

我有一个连接到 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 秒,看看是否有消息到达。我该怎么做?

【问题讨论】:

    标签: android socket.io android-espresso


    【解决方案1】:

    我已经通过编写一个自定义 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 应该为我提供的东西。事实上,它并没有让我相信我对这个测试的想法是错误的。有没有更好的方法来测试相同的行为?

    【讨论】:

    • 感谢您发布此信息。我根据需要修改了它!这个等待线性布局的子节点数大于零。孩子是动态添加的,我们需要确保至少有一个! gist.github.com/Emeritus-DarranKelinske/…
    • @Neo Ware 为什么叫 Espresso.unregisterIdlingResources(idler);注册后吗?那不是马上取消注册吗?
    猜你喜欢
    • 1970-01-01
    • 2015-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-23
    • 1970-01-01
    相关资源
    最近更新 更多