等待使用浓缩咖啡查看寻呼机动画?
Wait for view pager animations with espresso?
正在尝试使用 ViewPager 进行一些测试。
我想在选项卡之间滑动,并且在滑动完成之前不想继续。但是似乎没有办法关闭视图寻呼机的动画(开发者选项下的所有动画都被禁用)。
所以这总是导致测试失败,因为视图寻呼机还没有完成它的动画,所以视图还没有完全显示:
// swipe left
onView(withId(R.id.viewpager)).check(matches(isDisplayed())).perform(swipeLeft());
// check to ensure that the next tab is completely visible.
onView(withId(R.id.next_tab)).check(matches(isCompletelyDisplayed()));
是否有一种优雅的或什至推荐的方法来做到这一点,或者我是否坚持在那里放置某种定时等待?
你可以做很多工作并使用 IdlingResource to implement an OnPageChangeListener
或者简单地说:
SystemClock.sleep(500);
@Simas 建议的 IdlingResource
实际上实施起来非常简单:
public class ViewPagerIdlingResource implements IdlingResource {
private final String mName;
private boolean mIdle = true; // Default to idle since we can't query the scroll state.
private ResourceCallback mResourceCallback;
public ViewPagerIdlingResource(ViewPager viewPager, String name) {
viewPager.addOnPageChangeListener(new ViewPagerListener());
mName = name;
}
@Override
public String getName() {
return mName;
}
@Override
public boolean isIdleNow() {
return mIdle;
}
@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
mResourceCallback = resourceCallback;
}
private class ViewPagerListener extends ViewPager.SimpleOnPageChangeListener {
@Override
public void onPageScrollStateChanged(int state) {
mIdle = (state == ViewPager.SCROLL_STATE_IDLE
// Treat dragging as idle, or Espresso will block itself when swiping.
|| state == ViewPager.SCROLL_STATE_DRAGGING);
if (mIdle && mResourceCallback != null) {
mResourceCallback.onTransitionToIdle();
}
}
}
}
试试这个,
onView(withId(R.id.pager)).perform(pagerSwipeRight()).perform(pagerSwipeLeft());
private GeneralSwipeAction pagerSwipeRight(){
return new GeneralSwipeAction(Swipe.SLOW, GeneralLocation.CENTER_LEFT,
GeneralLocation.CENTER_RIGHT, Press.FINGER);
}
private GeneralSwipeAction pagerSwipeLeft(){
return new GeneralSwipeAction(Swipe.SLOW, GeneralLocation.CENTER_RIGHT,
GeneralLocation.CENTER_LEFT, Press.FINGER);
}
我对@vaughandroid 的方法有疑问,所以我对他的方法做了一些更改。一旦检测到正在发生滚动,此方法就会将 idle 设置为 false,并且 "force" ViewPager 使用 setCurrentItem() 完成滚动。
public class ViewPagerIdlingResource implements IdlingResource {
private volatile boolean mIdle = true; // Default to idle since we can't query the scroll state.
private ResourceCallback mResourceCallback;
private ViewPager mViewPager;
public static ViewPagerIdlingResource waitViewPagerSwipe(ViewPager viewPager) {
return new ViewPagerIdlingResource(viewPager);
}
private ViewPagerIdlingResource(ViewPager viewPager) {
mViewPager = viewPager;
mViewPager.addOnPageChangeListener(new ViewPagerListener());
}
@Override
public String getName() {
return ViewPagerIdlingResource.class.getSimpleName();
}
@Override
public boolean isIdleNow() {
return mIdle;
}
@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
mResourceCallback = resourceCallback;
}
private class ViewPagerListener extends ViewPager.SimpleOnPageChangeListener {
float mPositionOffset = 0.0f;
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (isSwipingToRight(positionOffset)) {
mIdle = false;
mViewPager.setCurrentItem(position + 1);
} else if (isSwipingToLeft(positionOffset)) {
mIdle = false;
mViewPager.setCurrentItem(position - 1);
}
mPositionOffset = positionOffset;
if (positionOffset == 0 && !mIdle && mResourceCallback != null) {
mResourceCallback.onTransitionToIdle();
mIdle = true;
mPositionOffset = 0.0f;
}
}
private boolean isSwipingToRight(float positionOffset) {
return mPositionOffset != 0.0f && positionOffset > mPositionOffset && mIdle;
}
private boolean isSwipingToLeft(float positionOffset) {
return mPositionOffset != 0.0f && positionOffset < mPositionOffset && mIdle;
}
}
}
我的目标是用 ViewPager2
使用 Facebook screenshot test library 制作屏幕截图。对我来说最简单的方法是检查几乎每一帧动画是否完成,如果是那么就该截图了:
fun waitForViewPagerAnimation(parentView: View) {
if (parentView is ViewGroup) {
parentView.childrenViews<ViewPager2>().forEach {
while (it.scrollState != ViewPager2.SCROLL_STATE_IDLE) {
Thread.sleep(16)
}
}
}
}
childrenViews
函数可以找到here
因为我现在至少做了两次,这里是 Kotlin 中的 和 androidx ViewPager2
:
class ViewPager2IdlingResource(viewPager: ViewPager2, name: String) : IdlingResource {
private val name: String
private var isIdle = true // Default to idle since we can't query the scroll state.
private var resourceCallback: IdlingResource.ResourceCallback? = null
init {
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageScrollStateChanged(state: Int) {
isIdle = (state == ViewPager.SCROLL_STATE_IDLE // Treat dragging as idle, or Espresso will block itself when swiping.
|| state == ViewPager.SCROLL_STATE_DRAGGING)
if (isIdle && resourceCallback != null) {
resourceCallback!!.onTransitionToIdle()
}
}
})
this.name = name
}
override fun getName(): String {
return name
}
override fun isIdleNow(): Boolean {
return isIdle
}
override fun registerIdleTransitionCallback(resourceCallback: IdlingResource.ResourceCallback) {
this.resourceCallback = resourceCallback
}
}
下面是使用 ActivityScenarioRule
在 UI 测试中使用它的方法:
@get:Rule
val testRule = ActivityScenarioRule(OnboardingActivity::class.java)
private lateinit var viewPager2IdlingResource: ViewPager2IdlingResource
....
@Before
fun setUp() {
testRule.scenario.onActivity {
viewPager2IdlingResource =
ViewPager2IdlingResource(it.findViewById(R.id.onboarding_view_pager), "viewPagerIdlingResource")
IdlingRegistry.getInstance().register(viewPager2IdlingResource)
}
}
@After
fun tearDown() {
IdlingRegistry.getInstance().unregister(viewPager2IdlingResource)
}
androidx.test.espresso:espresso-core library offers a ViewPagerActions class which contains a number of methods for scrolling between the pages of a ViewPager。它负责等待滚动完成,因此您无需在测试方法中添加任何显式等待或睡眠。
如果您需要在 ViewPager2 instance, you can take the source of the ViewPagerActions class from here and make some minor tweaks to it to get it to work for ViewPager2. Here 上执行类似的滚动,这是一个示例,欢迎您使用。
正在尝试使用 ViewPager 进行一些测试。
我想在选项卡之间滑动,并且在滑动完成之前不想继续。但是似乎没有办法关闭视图寻呼机的动画(开发者选项下的所有动画都被禁用)。
所以这总是导致测试失败,因为视图寻呼机还没有完成它的动画,所以视图还没有完全显示:
// swipe left
onView(withId(R.id.viewpager)).check(matches(isDisplayed())).perform(swipeLeft());
// check to ensure that the next tab is completely visible.
onView(withId(R.id.next_tab)).check(matches(isCompletelyDisplayed()));
是否有一种优雅的或什至推荐的方法来做到这一点,或者我是否坚持在那里放置某种定时等待?
你可以做很多工作并使用 IdlingResource to implement an OnPageChangeListener
或者简单地说:
SystemClock.sleep(500);
@Simas 建议的 IdlingResource
实际上实施起来非常简单:
public class ViewPagerIdlingResource implements IdlingResource {
private final String mName;
private boolean mIdle = true; // Default to idle since we can't query the scroll state.
private ResourceCallback mResourceCallback;
public ViewPagerIdlingResource(ViewPager viewPager, String name) {
viewPager.addOnPageChangeListener(new ViewPagerListener());
mName = name;
}
@Override
public String getName() {
return mName;
}
@Override
public boolean isIdleNow() {
return mIdle;
}
@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
mResourceCallback = resourceCallback;
}
private class ViewPagerListener extends ViewPager.SimpleOnPageChangeListener {
@Override
public void onPageScrollStateChanged(int state) {
mIdle = (state == ViewPager.SCROLL_STATE_IDLE
// Treat dragging as idle, or Espresso will block itself when swiping.
|| state == ViewPager.SCROLL_STATE_DRAGGING);
if (mIdle && mResourceCallback != null) {
mResourceCallback.onTransitionToIdle();
}
}
}
}
试试这个,
onView(withId(R.id.pager)).perform(pagerSwipeRight()).perform(pagerSwipeLeft());
private GeneralSwipeAction pagerSwipeRight(){
return new GeneralSwipeAction(Swipe.SLOW, GeneralLocation.CENTER_LEFT,
GeneralLocation.CENTER_RIGHT, Press.FINGER);
}
private GeneralSwipeAction pagerSwipeLeft(){
return new GeneralSwipeAction(Swipe.SLOW, GeneralLocation.CENTER_RIGHT,
GeneralLocation.CENTER_LEFT, Press.FINGER);
}
我对@vaughandroid 的方法有疑问,所以我对他的方法做了一些更改。一旦检测到正在发生滚动,此方法就会将 idle 设置为 false,并且 "force" ViewPager 使用 setCurrentItem() 完成滚动。
public class ViewPagerIdlingResource implements IdlingResource {
private volatile boolean mIdle = true; // Default to idle since we can't query the scroll state.
private ResourceCallback mResourceCallback;
private ViewPager mViewPager;
public static ViewPagerIdlingResource waitViewPagerSwipe(ViewPager viewPager) {
return new ViewPagerIdlingResource(viewPager);
}
private ViewPagerIdlingResource(ViewPager viewPager) {
mViewPager = viewPager;
mViewPager.addOnPageChangeListener(new ViewPagerListener());
}
@Override
public String getName() {
return ViewPagerIdlingResource.class.getSimpleName();
}
@Override
public boolean isIdleNow() {
return mIdle;
}
@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
mResourceCallback = resourceCallback;
}
private class ViewPagerListener extends ViewPager.SimpleOnPageChangeListener {
float mPositionOffset = 0.0f;
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (isSwipingToRight(positionOffset)) {
mIdle = false;
mViewPager.setCurrentItem(position + 1);
} else if (isSwipingToLeft(positionOffset)) {
mIdle = false;
mViewPager.setCurrentItem(position - 1);
}
mPositionOffset = positionOffset;
if (positionOffset == 0 && !mIdle && mResourceCallback != null) {
mResourceCallback.onTransitionToIdle();
mIdle = true;
mPositionOffset = 0.0f;
}
}
private boolean isSwipingToRight(float positionOffset) {
return mPositionOffset != 0.0f && positionOffset > mPositionOffset && mIdle;
}
private boolean isSwipingToLeft(float positionOffset) {
return mPositionOffset != 0.0f && positionOffset < mPositionOffset && mIdle;
}
}
}
我的目标是用 ViewPager2
使用 Facebook screenshot test library 制作屏幕截图。对我来说最简单的方法是检查几乎每一帧动画是否完成,如果是那么就该截图了:
fun waitForViewPagerAnimation(parentView: View) {
if (parentView is ViewGroup) {
parentView.childrenViews<ViewPager2>().forEach {
while (it.scrollState != ViewPager2.SCROLL_STATE_IDLE) {
Thread.sleep(16)
}
}
}
}
childrenViews
函数可以找到here
因为我现在至少做了两次,这里是 Kotlin 中的 ViewPager2
:
class ViewPager2IdlingResource(viewPager: ViewPager2, name: String) : IdlingResource {
private val name: String
private var isIdle = true // Default to idle since we can't query the scroll state.
private var resourceCallback: IdlingResource.ResourceCallback? = null
init {
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageScrollStateChanged(state: Int) {
isIdle = (state == ViewPager.SCROLL_STATE_IDLE // Treat dragging as idle, or Espresso will block itself when swiping.
|| state == ViewPager.SCROLL_STATE_DRAGGING)
if (isIdle && resourceCallback != null) {
resourceCallback!!.onTransitionToIdle()
}
}
})
this.name = name
}
override fun getName(): String {
return name
}
override fun isIdleNow(): Boolean {
return isIdle
}
override fun registerIdleTransitionCallback(resourceCallback: IdlingResource.ResourceCallback) {
this.resourceCallback = resourceCallback
}
}
下面是使用 ActivityScenarioRule
在 UI 测试中使用它的方法:
@get:Rule
val testRule = ActivityScenarioRule(OnboardingActivity::class.java)
private lateinit var viewPager2IdlingResource: ViewPager2IdlingResource
....
@Before
fun setUp() {
testRule.scenario.onActivity {
viewPager2IdlingResource =
ViewPager2IdlingResource(it.findViewById(R.id.onboarding_view_pager), "viewPagerIdlingResource")
IdlingRegistry.getInstance().register(viewPager2IdlingResource)
}
}
@After
fun tearDown() {
IdlingRegistry.getInstance().unregister(viewPager2IdlingResource)
}
androidx.test.espresso:espresso-core library offers a ViewPagerActions class which contains a number of methods for scrolling between the pages of a ViewPager。它负责等待滚动完成,因此您无需在测试方法中添加任何显式等待或睡眠。
如果您需要在 ViewPager2 instance, you can take the source of the ViewPagerActions class from here and make some minor tweaks to it to get it to work for ViewPager2. Here 上执行类似的滚动,这是一个示例,欢迎您使用。