Java 浓缩咖啡:如果视图存在则返回布尔值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20807131/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Espresso: return boolean if view exists
提问by Chad Bingham
I am trying to check to see if a view is displayed with Espresso. Here is some pseudo code to show what I am trying:
我正在尝试检查 Espresso 是否显示了视图。这是一些伪代码来显示我正在尝试的内容:
if (!Espresso.onView(withId(R.id.someID)).check(doesNotExist()){
// then do something
} else {
// do nothing, or what have you
}
But my problem is .check(doesNotExist())
does not return boolean. It is just an assertion. With UiAutomator I was able to just do something like so:
但我的问题是.check(doesNotExist())
不返回布尔值。这只是一个断言。使用 UiAutomator,我可以执行以下操作:
if (UiAutomator.getbyId(SomeId).exists()){
.....
}
采纳答案by ValeraZakharov
Conditional logic in tests is undesirable. With that in mind, Espresso's API was designed to guide the test author away from it (by being explicit with test actions and assertions).
测试中的条件逻辑是不可取的。考虑到这一点,Espresso 的 API 旨在引导测试作者远离它(通过明确的测试操作和断言)。
Having said that, you can still achieve the above by implementing your own ViewAction and capturing the isDisplayed check (inside the perform method) into an AtomicBoolean.
话虽如此,您仍然可以通过实现自己的 ViewAction 并将 isDisplayed 检查(在 perform 方法中)捕获到 AtomicBoolean 中来实现上述目的。
Another less elegant option - catch the exception that gets thrown by failed check:
另一个不太优雅的选项 - 捕获失败检查引发的异常:
try {
onView(withText("my button")).check(matches(isDisplayed()));
//view is displayed logic
} catch (NoMatchingViewException e) {
//view not displayed logic
}
Kotlin version with an extension function:
带有扩展功能的 Kotlin 版本:
fun ViewInteraction.isDisplayed(): Boolean {
try {
check(matches(ViewMatchers.isDisplayed()))
return true
} catch (e: NoMatchingViewException) {
return false
}
}
if(onView(withText("my button")).isDisplayed()) {
//view is displayed logic
} else {
//view not displayed logic
}
回答by user3411862
We need that functionality and I ended up implementing it below:
我们需要这个功能,我最终在下面实现了它:
https://github.com/marcosdiez/espresso_clone
https://github.com/marcosdiez/espresso_clone
if(onView(withText("click OK to Continue")).exists()){
doSomething();
} else {
doSomethingElse();
}
I hope it is useful for you.
我希望它对你有用。
回答by Dhiren Mudgil
You check with the below code also. If view is displayed it will click else it will pass on.
您还可以使用以下代码进行检查。如果显示视图,它将单击,否则它将继续传递。
onView(withText("OK")).withFailureHandler(new FailureHandler() {
@Override
public void handle(Throwable error, Matcher<View> viewMatcher){
}
}).check(matches(isDisplayed())).perform(customClick());
回答by TWiStErRob
I think to mimic UIAutomator you can do this:
(Though, I suggest rethinking your approach to have no conditions.)
我认为模仿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;
}
}
Also exists
without branching can be implemented really simple:
也exists
没有分支可以实现非常简单:
onView(withBlah()).check(exists()); // the opposite of doesNotExist()
public static ViewAssertion exists() {
return matches(anything());
}
Though most of the time it's worth checking for matches(isDisplayed())
anyway.
尽管在大多数情况下,matches(isDisplayed())
无论如何都值得检查。
回答by trooper
Based on the answer by Dhiren Mudgil, I ended up writing the following method:
根据 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];
}
I'm using this to help determine which View in a ViewFlipper is currently displayed.
我使用它来帮助确定当前显示的是 ViewFlipper 中的哪个视图。
回答by Morten L?vborg
It's been some time since this issue was stated, but as it is one of the top hit on Google when searching for ways to make sure a view is present, before doing any actions on it in Espresso, I would like to share my very basic way of handling this.
自从提出这个问题已经有一段时间了,但由于在搜索确保视图存在的方法时,它是 Google 上的热门话题之一,因此在 Espresso 中对其进行任何操作之前,我想分享我的非常基本的处理这个的方式。
1: Start out by writing an extension to ViewInteraction
:
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: Create a simple help method in your base class (to be used in all test classes):
2:在你的基类中创建一个简单的帮助方法(用于所有测试类):
fun viewExists(id: Int): Boolean {
return try {
onView(withId(id)).exists()
} catch (e: RuntimeException) {
false
}
}
With this you either get true
or false
from onView(withId(id)).exists()
, or safely catch the RuntimeException and return false
.
有了这个,您可以获取true
或false
来自onView(withId(id)).exists()
,或者安全地捕获 RuntimeException 并返回false
。
Normally a simple check to .exists()
would be sufficient, but in some cases, like when you are deleting ListView items until non is left -> when the last item is deleted, the ListView might no longer be present, then an Exception is thrown when trying to check if it exists.
通常一个简单的检查.exists()
就足够了,但在某些情况下,比如当你删除 ListView 项目直到非剩余时 -> 当最后一个项目被删除时,ListView 可能不再存在,然后在尝试时抛出异常检查它是否存在。
3: With the above implementation, it is safe to check if any view exists, since the RuntimeException
is handled nicely behind the scene:
3:通过上述实现,检查是否存在任何视图是安全的,因为在RuntimeException
幕后处理得很好:
if(viewExists(R.id.something)) {
//do something
}
//do something else
回答by Duncan McGregor
I think that what Espresso wants you to do is to change your logic to use doesNotExist()
我认为 Espresso 希望你做的是改变你的逻辑来使用 doesNotExist()
I have for example
我有例如
onView(snackBarMatcher).check(doesNotExist())
onView(withId(R.id.button)).perform(click())
onView(snackBarMatcher).check(matches(isDisplayed()))
回答by David
Why no one mentioned:
为什么没人提到:
onView(withId(R.id.some_view_id)).check(matches(not(doesNotExist())))
just add not
before doesNotExist. But if you use this logic a lot it's better to use a custom matcher.
只需在不存在not
之前添加。但是如果你经常使用这个逻辑,最好使用自定义匹配器。