我正在尝试检查Espresso是否显示视图。这是一些伪代码,用于显示我正在尝试的内容:
if (!Espresso.onView(withId(R.id.someID)).check(doesNotExist()){
// then do something
} else {
// do nothing, or what have you
}
但我的问题是.check(doesNotExist())
没有返回布尔值。这只是一个断言。使用UiAutomator,我能够做到这样的事情:
if (UiAutomator.getbyId(SomeId).exists()){
.....
}
答案 0 :(得分:65)
测试中的条件逻辑是undesirable。考虑到这一点,Espresso的API旨在引导测试作者远离它(通过明确的测试操作和断言)。
话虽如此,你仍然可以通过实现自己的ViewAction并将isDisplayed检查(在perform方法中)捕获到AtomicBoolean来实现上述目的。
另一个不太优雅的选项 - 捕获失败检查引发的异常:
try {
onView(withText("my button")).check(matches(isDisplayed()));
//view is displayed logic
} catch (NoMatchingViewException e) {
//view not displayed logic
}
答案 1 :(得分:9)
您也可以使用以下代码进行检查。如果显示视图,它将单击否则将传递。
onView(withText("OK")).withFailureHandler(new FailureHandler() {
@Override
public void handle(Throwable error, Matcher<View> viewMatcher){
}
}).check(matches(isDisplayed())).perform(customClick());
答案 2 :(得分:9)
我认为模仿UIAutomator你可以这样做:
(虽然,我建议重新考虑你没有条件的方法。)
ViewInteraction view = onView(withBlah(...)); // supports .inRoot(...) as well
if (exists(view)) {
view.perform(...);
}
@CheckResult
public static boolean exists(ViewInteraction interaction) {
try {
interaction.perform(new ViewAction() {
@Override public Matcher<View> getConstraints() {
return any(View.class);
}
@Override public String getDescription() {
return "check for existence";
}
@Override public void perform(UiController uiController, View view) {
// no op, if this is run, then the execution will continue after .perform(...)
}
});
return true;
} catch (AmbiguousViewMatcherException ex) {
// if there's any interaction later with the same matcher, that'll fail anyway
return true; // we found more than one
} catch (NoMatchingViewException ex) {
return false;
} catch (NoMatchingRootException ex) {
// optional depending on what you think "exists" means
return false;
}
}
没有分支的exists
也可以非常简单地实现:
onView(withBlah()).check(exists()); // the opposite of doesNotExist()
public static ViewAssertion exists() {
return matches(anything());
}
虽然大部分时间都值得检查matches(isDisplayed())
。
答案 3 :(得分:8)
我们需要这个功能,最后我在下面实现了它:
https://github.com/marcosdiez/espresso_clone
if(onView(withText("click OK to Continue")).exists()){
doSomething();
} else {
doSomethingElse();
}
我希望它对你有用。
答案 4 :(得分:4)
根据Dhiren Mudgil的回答,我最后编写了以下方法:
public static boolean viewIsDisplayed(int viewId)
{
final boolean[] isDisplayed = {true};
onView(withId(viewId)).withFailureHandler(new FailureHandler()
{
@Override
public void handle(Throwable error, Matcher<View> viewMatcher)
{
isDisplayed[0] = false;
}
}).check(matches(isDisplayed()));
return isDisplayed[0];
}
我正在使用它来帮助确定当前显示ViewFlipper中的哪个View。
答案 5 :(得分:1)
自从这个问题出现以来已经有一段时间了,但是由于它是Google在寻找确保视图存在的方式时最受关注的问题之一,因此我想在Espresso中对其进行任何操作之前,先分享一下我最基本的处理方式。
1:首先将扩展名写入ViewInteraction
:
fun ViewInteraction.exists(): Boolean {
val viewExists = AtomicReference<Boolean>()
this.perform(object : ViewAction {
override fun perform(uiController: UiController?, view: View?) {
viewExists.set(view != null)
}
override fun getConstraints(): Matcher<View>? {
return Matchers.allOf(ViewMatchers.withEffectiveVisibility(
ViewMatchers.Visibility.VISIBLE),
ViewMatchers.isAssignableFrom(View::class.java))
}
override fun getDescription(): String {
return "check if view exists"
}
})
return viewExists.get()
}
2:在基类中创建一个简单的帮助方法(将在所有测试类中使用):
fun viewExists(id: Int): Boolean {
return try {
onView(withId(id)).exists()
} catch (e: RuntimeException) {
false
}
}
使用此方法,您可以从true
获取false
或onView(withId(id)).exists()
,也可以安全地捕获RuntimeException并返回false
。
通常,对.exists()
进行简单检查就足够了,但是在某些情况下,例如,当您删除ListView项目直到剩下non时->删除最后一个项目时,ListView可能不再存在,然后在尝试检查异常是否存在时抛出异常。
3:通过上述实现,可以安全地检查是否存在任何视图,因为RuntimeException
在幕后得到了很好的处理:
if(viewExists(R.id.something)) {
//do something
}
//do something else
答案 6 :(得分:0)
我认为Espresso希望您做的是改变使用doesNotExist()
的逻辑
例如,我有
onView(snackBarMatcher).check(doesNotExist())
onView(withId(R.id.button)).perform(click())
onView(snackBarMatcher).check(matches(isDisplayed()))
答案 7 :(得分:0)
为什么没人提到:
onView(withId(R.id.some_view_id)).check(matches(not(doesNotExist())))
只需在dosNotExist之前添加not
。但是,如果您经常使用此逻辑,则最好使用自定义匹配器。