等待使用浓缩咖啡查看寻呼机动画?

时间:2015-06-25 17:28:01

标签: android-testing android-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()));

是否有一种优雅的,甚至是推荐的方式来做到这一点,还是我不想在那里进行某种定时的等待?

6 个答案:

答案 0 :(得分:26)

IdlingResource @Simas建议实际上非常简单:

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();
            }
        }
    }
}

答案 1 :(得分:0)

试试这个,

    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);
    }

答案 2 :(得分:0)

我遇到了@vaughandroid方法的问题,所以我对他的方法做了一些改动。一旦检测到正在发生滚动并且"强制"这种方法将空闲设置为假。 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;
        }
    }
}

答案 3 :(得分:0)

我的目标是使用Facebook screenshot test libraryViewPager2截屏。对我来说,最简单的方法是检查几乎每一帧动画是否完成,如果可以,那么该是截图了:

fun waitForViewPagerAnimation(parentView: View) {
    if (parentView is ViewGroup) {
        parentView.childrenViews<ViewPager2>().forEach {
            while (it.scrollState != ViewPager2.SCROLL_STATE_IDLE) {
                Thread.sleep(16)
            }
        }
    }
}

childrenViews函数可以找到here

答案 4 :(得分:0)

由于我现在至少做过两次,所以这是Kotlin中的accepted answer和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)
}

答案 5 :(得分:-4)

您可以做很多工作并使用IdlingResource来实施OnPageChangeListener

或简单地说:

SystemClock.sleep(500);