android.support.test.espresso.PerformException:在视图上执行“加载适配器数据”时出错

时间:2016-09-11 17:42:14

标签: android listview android-espresso listadapter android-espresso-recorder

我正在使用Espresso来测试我在搜索项目时出现的列表视图(如自动填充)。在用户在SearchView中输入内容之前,列表视图不会显示。即只有当用户在SearchView中输入内容时,我才将ListView设置为View.VISIBLE

当我尝试单击列表视图中的文本时出现此错误。 android.support.test.espresso.PerformException: Error performing 'load adapter data' on view 'with id:'。使用onData不起作用。

添加人工延迟是有效的,但我不确定这是不好的做法,因为它似乎违背了诸如onData等方法的目的。

我尝试了什么:

我的代码

此代码有效,但我不希望引入人为延迟。

public pickSuggestion(int index){

    /** artificial delay to allow list to appear. 
    This works but I shouldn't have to do this right? **/

    SystemClock.sleep(1000);

    onData(anything())
        .inAdapterView(withId(R.id.list))
        .atPosition(index)
        .onChildView(withId(R.id.mTextView))
        .perform(click());
}

2 个答案:

答案 0 :(得分:4)

  

添加人工延迟有效,但我不确定这是不是很糟糕   实践,因为它似乎打败了方法的目的,如   onData等。

您的func已获得static JSValueRef TestNativeFunc(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { printf("func\n"); return JSValueMakeNull(ctx); } void TestMain() { JSGlobalContextRef context = JSGlobalContextCreate(NULL); JSObjectRef func = JSObjectMakeFunctionWithCallback(context, NULL, &TestNativeFunc); JSValueProtect(context, func); JSObjectCallAsFunction(context, func, NULL, 0, NULL, NULL); JSObjectRef global_object = JSContextGetGlobalObject(context); JSStringRef f_str = JSStringCreateWithUTF8CString("f"); JSObjectSetProperty(context, global_object, f_str, func, 0, NULL); JSStringRef script = JSStringCreateWithUTF8CString("f();"); JSEvaluateScript(context, script, NULL, NULL, 1, NULL); JSStringRelease(f_str); JSValueUnprotect(context, func); JSGlobalContextRelease(context); } 限制。这个框架需要在UI线程上运行,它等待'直到它会闲置它不会等待加载适配器数据,但等待获取空闲资源

检查:http://dev.jimdo.com/2014/05/09/wait-for-it-a-deep-dive-into-espresso-s-idling-resources/

IdlingResource参考:https://developer.android.com/reference/android/support/test/espresso/IdlingResource.html

IdlingResource文档:https://google.github.io/android-testing-support-library/docs/espresso/idling-resource/index.html

CountingIdlingResource:https://developer.android.com/reference/android/support/test/espresso/idling/CountingIdlingResource.html

errorEspresso之类的代码是一种不好的做法,因为更好的设备不需要这么多时间而旧的设备需要更多时间,因此您的代码可能不稳定,而不是快速灵活

解决方案是创建自己的SystemClock.sleep(1000)告诉Espresso何时可以执行测试而不会丢失数据和时间。

希望这会有所帮助。

答案 1 :(得分:0)

获得相同的错误消息在视图中执行'加载适配器数据'时出错,这些帖子的答案都不适合我。

Testing RecyclerView if it has data with Espresso
Espresso onData Error performing 'load adapter data' on view
Espresso. Error performing 'load adapter data'

我最终在Android Studio中使用了Espresso UI test recorder。从顶部下拉菜单转到运行,然后点击记录Espresso测试。它将要求您选择要运行的设备,一旦启动应用程序,手动执行您想要执行的ui测试并在需要时添加断言。完成后点击确定。它将为您生成UI测试文件。

点击RecyclerView 上的项目生成的代码如下所示。这里繁重的是匹配方法childAtPosition() 在测试开始时,它会睡眠10秒以确保所有内容都已加载,通常不需要10秒,您可以将其减少到大约2秒。另一种方法是使用类似@piotrek1543建议的Espresso IdlingResource,但这需要在生产代码中添加干预措施(混合测试特定代码)以适应测试。

@LargeTest
@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

    @Rule
    public ActivityTestRule<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class);

    @Test
    public void mainActivityTest() {
        // Added a sleep statement to match the app's execution delay.
        // The recommended way to handle such scenarios is to use Espresso idling resources:
        // https://google.github.io/android-testing-support-library/docs/espresso/idling-resource/index.html
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        ViewInteraction recyclerView = onView(
                allOf(withId(R.id.recycler_view_list),
                        childAtPosition(
                                withClassName(is("android.support.constraint.ConstraintLayout")),
                                0)));
        recyclerView.perform(actionOnItemAtPosition(0, click()));
    }

    private static Matcher<View> childAtPosition(
            final Matcher<View> parentMatcher, final int position) {

        return new TypeSafeMatcher<View>() {
            @Override
            public void describeTo(Description description) {
                description.appendText("Child at position " + position + " in parent ");
                parentMatcher.describeTo(description);
            }

            @Override
            public boolean matchesSafely(View view) {
                ViewParent parent = view.getParent();
                return parent instanceof ViewGroup && parentMatcher.matches(parent)
                        && view.equals(((ViewGroup) parent).getChildAt(position));
            }
        };
    }
}

注意:Espresso UI测试记录器生成的代码也不完美,大部分时间都可以使用,但不是100%