Android Espresso - 如何确认 swipeLeft() 确实滑动了?
Android Espresso - How to confirm swipeLeft() actually swiped?
我有一个 viewpager,其中至少有 4 个元素,但它是动态的,可以有超过 4 个元素。我想测试我是否能够至少滑动 pager 4 次。该测试正在测试 viewPager 至少有 4 个我可以滑动到的元素。我怎样才能做到这一点。这是我目前所拥有的:
int numOfPages = 4;
do {
onView(withId(R.id.pager)), matches(isDisplayed());
onView(withId(R.id.pager))
.perform(swipeLeft());
numOfPages--;
} while (numOfPages > 0);
但这只是向左滑动至少 4 次。如果我将 numOfPages 更改为 15,它只会尝试滑动 15 次而不会引发任何错误。那么我怎么知道测试是否成功? viewpager 中的 Fragments 不可点击,它们只显示图像。
您可以使用自定义匹配器检查 viewPager.getCurrentItem() 是否符合您的期望:
@Test
public void swipeFirstPages() {
int numPages = 4;
for (int i = 0; i < numPages; i++) {
// Check the ViewPager is in page i
onView(withId(R.id.pager)).check(matches(inPage(i)));
if (i < numPages - 1) { // perform swipe if not on last page
onView(withId(R.id.pager)).perform(swipeLeft());
SystemClock.sleep(800);
}
}
}
在 inPage 匹配器中使用的代码:
/**
* Returns a matcher that matches {@link ViewPager}s based on currentItem property value.
*
* @param page {@link Matcher} of ViewPager's currentItem
*/
@NonNull
public static Matcher<View> inPage(final int page) {
return new BoundedMatcher<View, ViewPager>(ViewPager.class) {
@Override
public void describeTo(final Description description) {
description.appendText("in page: " + page);
}
@Override
public boolean matchesSafely(final ViewPager viewPager) {
return viewPager.getCurrentItem() == page;
}
};
}
如果您想在每次滑动后避免 SystemClock.sleep,您可以使用 。
如果您只关心页数,那么编写断言有 n 或多于 n 页的 ViewMatcher 是微不足道的:
fun withNumberOfPages(numberOfPages: Matcher<Int>): Matcher<View> {
return object : BoundedMatcher<View, ViewPager>(ViewPager::class.java) {
override fun describeTo(description: Description) {
description.appendText("with ")
numberOfPages.describeTo(description)
description.appendText("number of pages")
}
override fun matchesSafely(viewPager: ViewPager): Boolean {
return numberOfPages.matches(viewPager.adapter?.count ?: -1)
}
}
}
如果你真的想知道寻呼机是否 "swipeable" 至少 4 次,我们可以添加另一个匹配器,断言每次滑动后寻呼机在第 n 页:
fun withSelectedPage(selection: Int): Matcher<View> {
return object : BoundedMatcher<View, ViewPager>(ViewPager::class.java) {
private var actualSelection = -1
override fun describeTo(description: Description) {
if (actualSelection != -1) {
description.appendText("with $selection page selected")
description.appendText("\n But page $actualSelection was selected")
}
}
override fun matchesSafely(viewPager: ViewPager): Boolean {
actualSelection = viewPager.currentItem
return selection == actualSelection
}
}
}
用法如下:
onView(withId(R.id.pager)).check(matches(withNumberOfPages(Matchers.greaterThan(4))))
&&
onView(withId(R.id.pager)).check(matches(withSelectedPage(1)))
但这里的另一个哲学问题是它实际上测试了什么吗?可能是。但根据实际业务需求,它可能实际上没有帮助。
用户如何知道刷卡成功?他们可能在屏幕上看到了一些东西。 espresso 的想法是以类似的方式进行测试。如果对页面上的内容有真正的兴趣,那么一切都归结为用于测试的密封环境。如果您无法控制测试接收到的数据,那么您就没有进行太多测试。如果您可以模拟传入的数据,那么 vewpager 将始终设置为相同数量的页面,您将知道每个页面包含什么。这将使您的测试更加独立、确定并提供实际价值。
我有一个 viewpager,其中至少有 4 个元素,但它是动态的,可以有超过 4 个元素。我想测试我是否能够至少滑动 pager 4 次。该测试正在测试 viewPager 至少有 4 个我可以滑动到的元素。我怎样才能做到这一点。这是我目前所拥有的:
int numOfPages = 4;
do {
onView(withId(R.id.pager)), matches(isDisplayed());
onView(withId(R.id.pager))
.perform(swipeLeft());
numOfPages--;
} while (numOfPages > 0);
但这只是向左滑动至少 4 次。如果我将 numOfPages 更改为 15,它只会尝试滑动 15 次而不会引发任何错误。那么我怎么知道测试是否成功? viewpager 中的 Fragments 不可点击,它们只显示图像。
您可以使用自定义匹配器检查 viewPager.getCurrentItem() 是否符合您的期望:
@Test
public void swipeFirstPages() {
int numPages = 4;
for (int i = 0; i < numPages; i++) {
// Check the ViewPager is in page i
onView(withId(R.id.pager)).check(matches(inPage(i)));
if (i < numPages - 1) { // perform swipe if not on last page
onView(withId(R.id.pager)).perform(swipeLeft());
SystemClock.sleep(800);
}
}
}
在 inPage 匹配器中使用的代码:
/**
* Returns a matcher that matches {@link ViewPager}s based on currentItem property value.
*
* @param page {@link Matcher} of ViewPager's currentItem
*/
@NonNull
public static Matcher<View> inPage(final int page) {
return new BoundedMatcher<View, ViewPager>(ViewPager.class) {
@Override
public void describeTo(final Description description) {
description.appendText("in page: " + page);
}
@Override
public boolean matchesSafely(final ViewPager viewPager) {
return viewPager.getCurrentItem() == page;
}
};
}
如果您想在每次滑动后避免 SystemClock.sleep,您可以使用
如果您只关心页数,那么编写断言有 n 或多于 n 页的 ViewMatcher 是微不足道的:
fun withNumberOfPages(numberOfPages: Matcher<Int>): Matcher<View> {
return object : BoundedMatcher<View, ViewPager>(ViewPager::class.java) {
override fun describeTo(description: Description) {
description.appendText("with ")
numberOfPages.describeTo(description)
description.appendText("number of pages")
}
override fun matchesSafely(viewPager: ViewPager): Boolean {
return numberOfPages.matches(viewPager.adapter?.count ?: -1)
}
}
}
如果你真的想知道寻呼机是否 "swipeable" 至少 4 次,我们可以添加另一个匹配器,断言每次滑动后寻呼机在第 n 页:
fun withSelectedPage(selection: Int): Matcher<View> {
return object : BoundedMatcher<View, ViewPager>(ViewPager::class.java) {
private var actualSelection = -1
override fun describeTo(description: Description) {
if (actualSelection != -1) {
description.appendText("with $selection page selected")
description.appendText("\n But page $actualSelection was selected")
}
}
override fun matchesSafely(viewPager: ViewPager): Boolean {
actualSelection = viewPager.currentItem
return selection == actualSelection
}
}
}
用法如下:
onView(withId(R.id.pager)).check(matches(withNumberOfPages(Matchers.greaterThan(4))))
&&
onView(withId(R.id.pager)).check(matches(withSelectedPage(1)))
但这里的另一个哲学问题是它实际上测试了什么吗?可能是。但根据实际业务需求,它可能实际上没有帮助。
用户如何知道刷卡成功?他们可能在屏幕上看到了一些东西。 espresso 的想法是以类似的方式进行测试。如果对页面上的内容有真正的兴趣,那么一切都归结为用于测试的密封环境。如果您无法控制测试接收到的数据,那么您就没有进行太多测试。如果您可以模拟传入的数据,那么 vewpager 将始终设置为相同数量的页面,您将知道每个页面包含什么。这将使您的测试更加独立、确定并提供实际价值。