Android Espresso 启动活动测试

Android Espresso startActivity testing

我有:

        onView(withId(R.id.login_email_textview)).perform(clearText(), closeSoftKeyboard());
        onView(withId(R.id.password_edittext)).perform(clearText(), closeSoftKeyboard());
        onView(withId(R.id.login_email_textview)).perform(typeText(email), closeSoftKeyboard());
        onView(withId(R.id.password_edittext)).perform(typeText(password), closeSoftKeyboard());
        onView(withId(R.id.email_sign_in_button)).perform(click());
        intended(hasComponent(new ComponentName(getTargetContext(), MainActivity.class)));

按下登录按钮后,会出现加载对话框,异步任务会调用服务器来检查凭据。响应 LoginActivity 后, 我正在测试调用 finish() 并启动 MainActivity。

按下登录按钮后测试挂起。 同时使用:

@Rule
public IntentsTestRule<LoginActivity> mActivityRule = new IntentsTestRule<>(LoginActivity.class);

同样在我的代码中 I/m 调用 startActivity() 之后,我在 LoginActivity 上调用 finish()。

在 sign_in_button 我正在呼叫 Volley 请求。

如何解决您的问题

我假设 LoadingDialog 正在显示动画 ProgressBar

同时使用 ProgressBarVolley 实际上是个不错的主意。 ProgressBar 将强制 Espresso 等待,直到 Volley 在后台完成其工作。

我假设,你的测试 "hang" 因为你没有关闭 LoadingDialog。因此,要解决此问题,请在收到 Volley 的响应时关闭 LoadingDialog。但是不要使用 Espresso 来关闭 LoadingDialog.

更多信息

单独使用ProgressBarVolley时有"known issues":

ProgressBar

的问题

如果 LoadingDialog 显示动画 ProgressBar,则动画块 Espresso。动画使应用程序的主线程保持忙碌,Espresso 一直等到超时。

See here for workarounds

Volley

的问题

Espresso 不知道 Volley。如果 Volley 在后台线程中执行请求(我希望如此),Espresso 不会等待,您的测试可能会在 Volley returns 响应之前结束。

一个IdlingResource可以用来让Espresso等待任何事情。

这就是我想出的解决方案:

自定义空闲资源:

public class VolleyIdlingResource implements IdlingResource {
private static final String TAG = "VolleyIdlingResource";
private final String resourceName;

// written from main thread, read from any thread.
private volatile ResourceCallback resourceCallback;

private Field requests;
private RequestQueue requestQueue;

public VolleyIdlingResource(String resourceName, Context context) throws SecurityException, NoSuchFieldException {
    this.resourceName = checkNotNull(resourceName);

    requestQueue = MyApplication.get(context).getRequestQueue();

    requests = RequestQueue.class.getDeclaredField("requests");
    requests.setAccessible(true);
}

@Override
public String getName() {
    return resourceName;
}

@Override
public boolean isIdleNow() {
    try {
        Set<Request> set = (Set<Request>) requests.get(requestQueue);
        int count = set.size();
        if (set != null) {

            if (count == 0) {
                resourceCallback.onTransitionToIdle();
            } else {
            }
            return count == 0;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return true;
}

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

然后在测试中:

VolleyIdlingResource volleyResources;
        try {
            volleyResources = new VolleyIdlingResource("VolleyCalls", mActivityRule.getActivity());
            registerIdlingResources(volleyResources);
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        intended(hasComponent(new ComponentName(getTargetContext(), MainActivity.class)));

基于https://github.com/bolhoso/espresso-volley-tests/blob/master/EspressoTest/src/com/example/espressovolley/test/MyTest.java