Java Espresso - 如何检查是否显示其中一个视图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29250506/
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 - How to check if one of the view is displayed
提问by user846316
In my test, after one action, there are two possible views which can appear and both of them are correct. How can I check if one of the view is displayed. For a single view I can check with is Displayed(). But that would fail if other view is visible instead. I want to pass the test if any one of those two views are displayed.
在我的测试中,在一个动作之后,可以出现两种可能的视图,并且它们都是正确的。如何检查是否显示了其中一个视图。对于我可以检查的单个视图是 Displayed()。但是如果其他视图是可见的,那将会失败。如果显示这两个视图中的任何一个,我想通过测试。
onMyButton.perform(click());
onMyPageOne.check(matches(isDisplayed())); //view 1
or
onMyPageTwo.check(matches(isDisplayed())); //view 2
After, perform click on MyButton, any one of the view (1 or 2) is expected to appear but not both. It is not fixed that which one would be displayed. How can I check if any one of them is displayed?
之后,单击 MyButton,预期会出现任何一个视图(1 或 2),但不会同时出现。不固定显示哪一个。如何检查是否显示了其中任何一个?
回答by The Original Android
One simple way to check for a View or its subclass like a Button is to use method getVisibilityfrom Viewclass. I must caution that visibility attribute is not clearly defined in the GUI world. A view may be considered visible but may be overlapped with another view, for one example, making it hidden.
一个简单的方法来检查查看或它的子类如Button是使用方法 getVisibility从视图类。我必须警告,在 GUI 世界中没有明确定义可见性属性。一个视图可能被认为是可见的,但可能与另一个视图重叠,例如,使其隐藏。
Another way but more accurate (I have not tried) is to check for the rectangular bounds of the View. Not so simple.
另一种更准确的方法(我没有尝试过)是检查视图的矩形边界。没那么简单。
Is that clear enough? cannot give you specific examples since you did not post code.
这够清楚了吗?由于您没有发布代码,因此无法为您提供具体示例。
回答by The Original Android
I researched Espresso a bit, and I found this @ Espresso Samples.
我对 Espresso 进行了一些研究,我发现了这个 @ Espresso Samples。
Search text "Asserting that a view is not displayed". It says "The above approach works if the view is still part of the hierarchy." So I think your code should work but you need to use
ViewAssertions
also. Using your code, perhaps do this:if (ViewAssertions.doesNotExist()) == null) { return; } onMyPageOne.check(matches(isDisplayed()));
Another technique is check for UI existence. Search for text "Asserting that a view is not present". Using your code, my best suggestion is:
onMyPageOne.check(doesNotExist());
搜索文本“断言不显示视图”。它说“如果视图仍然是层次结构的一部分,则上述方法有效。” 所以我认为你的代码应该可以工作,但你也需要使用
ViewAssertions
。使用您的代码,也许可以这样做:if (ViewAssertions.doesNotExist()) == null) { return; } onMyPageOne.check(matches(isDisplayed()));
另一种技术是检查 UI 是否存在。搜索文本“断言视图不存在”。使用您的代码,我最好的建议是:
onMyPageOne.check(doesNotExist());
Note: This calls doesNotExist
method.
注意:这会调用doesNotExist
方法。
Their sample code is: onView(withId(R.id.bottom_left)).check(doesNotExist());
他们的示例代码是: onView(withId(R.id.bottom_left)).check(doesNotExist());
回答by Dmitry Gr
The problem is that all assertoin()
and check()
methods return Assertion
that stops test flow if failed.
问题是如果失败,所有assertoin()
和check()
方法都会返回Assertion
停止测试流程。
回答by Lafayette
It's possible to catch the exceptions raised by Espresso like this:
可以像这样捕获 Espresso 引发的异常:
If you want to test if a view is in hierarchy:
如果要测试视图是否在层次结构中:
try {
onView(withText("Button")).perform(click());
// View is in hierarchy
} catch (NoMatchingViewException e) {
// View is not in hierarchy
}
This exception will be thrown if the view is notin the hierarchy.
如果视图不在层次结构中,将抛出此异常。
Sometimes the view can be in the hierarchy, but we need to test if it is displayed, so there is another exception for assertions, like this:
有时视图可以在层次结构中,但是我们需要测试它是否显示,因此断言还有另一个例外,如下所示:
try {
onView(withText("Button")).check(matches(isDisplayed()));
// View is displayed
} catch (AssertionFailedError e) {
// View not displayed
}
回答by eleven
Utility class which allows to check if view is visible
, gone
or invisible
:
允许检查视图是否为visible
,gone
或 的实用程序类invisible
:
public class ExtraAssertions {
public static ViewAssertion isVisible() {
return new ViewAssertion() {
public void check(View view, NoMatchingViewException noView) {
assertThat(view, new VisibilityMatcher(View.VISIBLE));
}
};
}
public static ViewAssertion isGone() {
return new ViewAssertion() {
public void check(View view, NoMatchingViewException noView) {
assertThat(view, new VisibilityMatcher(View.GONE));
}
};
}
public static ViewAssertion isInvisible() {
return new ViewAssertion() {
public void check(View view, NoMatchingViewException noView) {
assertThat(view, new VisibilityMatcher(View.INVISIBLE));
}
};
}
private static class VisibilityMatcher extends BaseMatcher<View> {
private int visibility;
public VisibilityMatcher(int visibility) {
this.visibility = visibility;
}
@Override public void describeTo(Description description) {
String visibilityName;
if (visibility == View.GONE) visibilityName = "GONE";
else if (visibility == View.VISIBLE) visibilityName = "VISIBLE";
else visibilityName = "INVISIBLE";
description.appendText("View visibility must has equals " + visibilityName);
}
@Override public boolean matches(Object o) {
if (o == null) {
if (visibility == View.GONE || visibility == View.INVISIBLE) return true;
else if (visibility == View.VISIBLE) return false;
}
if (!(o instanceof View))
throw new IllegalArgumentException("Object must be instance of View. Object is instance of " + o);
return ((View) o).getVisibility() == visibility;
}
}
}
And usage could look like this:
用法可能如下所示:
onView(withId(R.id.text_message)).check(isVisible());
Another view assertion which could help to check extra visibility properties of a view and its parents: it checks visibility
, isAttachedToWindow
, alpha
:
另一个视图断言可以帮助检查视图及其父视图的额外可见性属性:它检查visibility
, isAttachedToWindow
, alpha
:
class IsVisible : ViewAssertion {
override fun check(view: View, noViewFoundException: NoMatchingViewException?) {
ViewMatchers.assertThat(
"View is not visible. " +
"visibility: ${view.visibility}, " +
"isAttachedToWindow: ${view.isAttachedToWindow}, " +
"alpha: ${view.alpha}",
true, `is`(isViewTreeVisible(view)))
}
private fun isViewTreeVisible(view: View?): Boolean {
return if (view != null) {
val viewVisible = view.isAttachedToWindow && view.visibility == View.VISIBLE && view.alpha == 1.0f
if (view.parent !is View) viewVisible
else viewVisible && isViewTreeVisible(view.parent as View)
} else {
true
}
}
}
回答by Luiz Augusto
You can use Matchers.anyOfto check if any of the two views are displayed:
您可以使用Matchers.anyOf来检查是否显示了两个视图中的任何一个:
onView(
anyOf(withId(R.id.view_1), withId(R.id.view_2))
).check(matches(isDisplayed()));
回答by RyPope
There are two cases here that you could be trying to cover. The first is if you are checking if the view "is displayed on the screen to the user"in which case you would use isDisplayed()
这里有两种情况您可以尝试涵盖。第一个是如果您正在检查视图是否“向用户显示在屏幕上”,在这种情况下您将使用isDisplayed()
onView(matcher).check(matches(isDisplayed()));
or the negation
或否定
onView(matcher).check(matches(not(isDisplayed())));
The other case is if you are checking if the view is visible but not necessarily displayed on the screen (ie. an item in a scrollview). For this you can use withEffectiveVisibility(Visibility)
另一种情况是,如果您正在检查视图是否可见但不一定显示在屏幕上(即滚动视图中的项目)。为此,您可以使用withEffectiveVisibility(Visibility)
onView(matcher).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)));
回答by dira
final AtomicBoolean view1Displayed = new AtomicBoolean(true);
Espresso.onView(ViewMatchers.withId(viewId1)).inRoot(RootMatchers.withDecorView(Matchers.is(intentsTestRule.getActivity().getWindow().getDecorView()))).withFailureHandler(new FailureHandler() {
@Override
public void handle(Throwable error, Matcher<View> viewMatcher) {
view1Displayed.set(false);
}
}).check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
if (view1Displayed.get()) {
try {
Espresso.onView(ViewMatchers.withId(viewId2)).inRoot(RootMatchers.withDecorView(Matchers.is(intentsTestRule.getActivity().getWindow().getDecorView()))).check(ViewAssertions.matches(Matchers.not(ViewMatchers.isDisplayed())));
} catch (NoMatchingViewException ignore) {
}
} else {
Espresso.onView(ViewMatchers.withId(viewId2)).inRoot(RootMatchers.withDecorView(Matchers.is(intentsTestRule.getActivity().getWindow().getDecorView()))).check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
}
回答by dgngulcan
For the ones looking to check the visibility status for a view; here are some utility functions I use.
对于那些希望检查视图可见性状态的人;这是我使用的一些实用功能。
fun ViewInteraction.isGone() = getViewAssertion(ViewMatchers.Visibility.GONE)
fun ViewInteraction.isVisible() = getViewAssertion(ViewMatchers.Visibility.VISIBLE)
fun ViewInteraction.isInvisible() = getViewAssertion(ViewMatchers.Visibility.INVISIBLE)
private fun getViewAssertion(visibility: ViewMatchers.Visibility): ViewAssertion? {
return ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(visibility))
}
And can be used as follows
并且可以如下使用
onView(withId(R.id.progressBar)).isVisible()
onView(withId(R.id.progressBar)).isGone()
回答by Michael Osofsky
When I face this situation I generally split into multiple tests. One test sets the conditions for view #1 to be displayed and the other test sets the conditions for view #2 to be displayed.
当我遇到这种情况时,我通常会分成多个测试。一个测试设置视图#1 的显示条件,另一个测试设置视图#2 的显示条件。
But let's say that you can't really control the conditions. For example, what if it depends on a random number or it depends on a third-party resource such as a calculation on a server? In that case, I usually solve the problem mocking. That way I can control the conditions so I know exactly which view to expect. I use Dependency Injection to set the mock I need for each test.
但是,假设您无法真正控制条件。例如,如果它依赖于一个随机数,或者它依赖于服务器上的计算等第三方资源呢?在这种情况下,我通常会通过模拟来解决问题。这样我就可以控制条件,所以我确切地知道期望哪个视图。我使用依赖注入来设置每个测试所需的模拟。