工作流程应如下:
到目前为止,我已经为 1,3,5 的步骤编写了断言,并且它完美运行:
onView(withText("foo 1"))
.check(matches(isDisplayed()));
问题是,我不知道如何让espresso知道验证进度条的可见性在之前发出请求在发出请求之后。
考虑onCreate()
方法如下:
super.onCreate(...);
setContentView(...);
showProgressBar(true);
apiClient.getStuff(new Callback() {
public void onSuccess() {
showProgressBar(false);
}
});
我尝试过以下操作但不起作用:
// Activity is launched at this point.
activityRule.launchActivity(new Intent());
// Up to this point, the request has been fired and response was
// returned, so the progress bar is now GONE.
onView(withId(R.id.progress_bar))
.check(matches(isDisplayed()));
onView(withId(R.id.progress_bar))
.check(matches(not(isDisplayed())));
之所以发生这种情况,是因为,由于客户端已注册为闲置资源,因此在运行第一个onView(...progressbar...)...
之前espresso会再次等待空闲,所以我需要一种方式让espresso知道运行 BEFORE 进入闲置状态。
编辑:这也不起作用:
idlingResource.registerIdleTransitionCallback(new IdlingResource.ResourceCallback() {
@Override
public void onTransitionToIdle() {
onView(withId(R.id.progress_bar))
.check(matches(isDisplayed()));
}
});
答案 0 :(得分:13)
Espresso有动画问题。你可以将进度条的drawable设置为静态的,仅用于测试,它可以按预期工作。
Drawable notAnimatedDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.whatever);
((ProgressBar) getActivity().findViewById(R.id.progress_bar)).setIndeterminateDrawable(notAnimatedDrawable);
onView(withId(R.id.progress_bar)).check(matches(isDisplayed()));
答案 1 :(得分:5)
正如我所看到的,Espresso
与跳过动态UI操作紧密相关,这就是您无法使用ProgressBar
测试Espresso
的原因。但是,您可以使用其他Android Google工具轻松完成此操作:UiAutomator
如下:
saveButton().click(); // perform action opening ProgressBar with UiAutomator, not Espresso
assertTrue(progressBar().exists());
使用这些静态工具:
public static UiObject progressBar() {
return uiObjectWithText(R.string.my_progress);
}
public static UiObject saveButton() {
return uiObjectWithId(R.id.my_save_button);
}
public static UiObject uiObjectWithId(@IdRes int id) {
String resourceId = getTargetContext().getResources().getResourceName(id);
UiSelector selector = new UiSelector().resourceId(resourceId);
return UiDevice.getInstance(getInstrumentation()).findObject(selector);
}
public static UiObject uiObjectWithText(@StringRes int stringRes) {
UiSelector selector = new UiSelector().text(getTargetContext().getString(stringRes));
return UiDevice.getInstance(getInstrumentation()).findObject(selector);
}
确保您的build.gradle
包含:
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
答案 2 :(得分:4)
看起来这可能不是真的可能。虽然它是一个较旧的组发布,但在Android Test Kit Discussion中有一个相当决定性的答案,其中声明UI线程在进度条动画期间不会休息,因此Espresso框架无法执行。
Marcus Klepp建议通过使用构建类型来超越此here。 Gradle插件允许您定义不同的build types。您可以在androidTest
构建类型中设置不同的布局,以使用通用的内容替换相关的View
。如果你所做的只是在一组条件下确认小部件isDisplayed()
,而在另一组条件下确认not(isDisplayed())
,那么你肯定可以通过不同的布局文件来实现它。并不是说它不是一点点提升。
最后,此处可能还有其他帖子,其中包含一些其他信息:"java.lang.RuntimeException: Could not launch intent" for UI with indeterminate ProgressBar
答案 3 :(得分:0)
就我而言,上面提供的解决方案也可以,但是我简化了,因此添加了build.gradle
uiautomator库
androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'
并创建了一个新类,该类可以与“进度栏”一起使用
public class ProgressBarHandler {
public static void waitUntilGoneProgressBar() {
progressBar().waitUntilGone(10000);
}
private static UiObject progressBar() {
return uiObjectWithId(R.id.progress_bar);
}
private static UiObject uiObjectWithId(@IdRes int id) {
String resourceId = getTargetContext().getResources().getResourceName(id);
UiSelector selector = new UiSelector().resourceId(resourceId);
return UiDevice.getInstance(getInstrumentation()).findObject(selector);
}
}
在我的测试中使用所有Espresso方法,仅在需要时才在测试中使用UiAutomator,例如
public class LoginTest extends AbstractTest {
@Rule
public ActivityTestRule<LoginActivity> createAccountActivityTestRule = new ActivityTestRule<>(LoginActivity.class);
@Test
public void loginTest() {
onView(withId(R.id.login_email)).perform(typeText("autotest666@gmail.com"));
onView(withId(R.id.input_password)).perform(typeText("Password123."));
onView(withId(R.id.login_log_in)).perform(click());
waitUntilGoneProgressBar();
onView(withId(R.id.fragment_home_title)).check(matches(isDisplayed()));
}