Android 闲置资源

示例

闲置资源的力量在于不必等待某些应用程序的处理(联网,计算,动画等)完成sleep(),这会带来脆弱性和/或延长测试的运行时间。官方文档可以在这里找到。

实作

实施IdlingResource接口时,需要做三件事:

  • getName() -返回空闲资源的名称。

  • isIdleNow() -检查您的xyz对象,操作等当前是否处于空闲状态。

  • registerIdleTransitionCallback(IdlingResource.ResourceCallbackcallback)-提供一个回调,当对象转换为空闲状态时应调用该回调。

现在,您应该创建自己的逻辑,并确定您的应用何时处于空闲状态以及何时不处于空闲状态,因为这取决于应用程序。在下面,您将找到一个简单的示例,仅用于演示其工作原理。在线上还有其他示例,但是特定的应用程序实现带来了特定的空闲资源实现。

笔记

  • 在Google的一些示例中,他们将IdlingResources应用程序代码放入其中。不要这样做。他们大概把它放在那里只是为了展示他们的工作方式。

  • 保持代码整洁并保持单一责任原则取决于您!

示例

假设您有一个活动,它做的事情很奇怪,并且需要很长的时间才能加载片段,从而使Espresso测试失败,因为无法从片段中找到资源(您应该更改活动的创建方式和时间加快速度)。但是为了简单起见,下面的示例显示了它的外观。

我们的示例空闲资源将获得两个对象:

  • 您需要查找并等待连接到活动的片段的标签

  • 一个FragmentManager对象,用于查找片段。

/**
 * FragmentIdlingResource - idling resource which waits while Fragment has not been loaded.
 */
public class FragmentIdlingResource implements IdlingResource {
    private final FragmentManager mFragmentManager;
    private final String mTag;
    //活动转换为空闲时使用的资源回调
    private volatile ResourceCallback resourceCallback;

    public FragmentIdlingResource(FragmentManager fragmentManager, String tag) {
        mFragmentManager = fragmentManager;
        mTag = tag;
    }

    @Override
    public String getName() {
        return FragmentIdlingResource.class.getName() + ":" + mTag;
    }

    @Override
    public boolean isIdleNow() {
        //简单检查,如果添加了片段,则您的应用程序变得空闲
        boolean idle = (mFragmentManager.findFragmentByTag(mTag) != null);
        if (idle) {
            //重要说明:确保您调用onTransitionToIdle
            resourceCallback.onTransitionToIdle();
        }
        return idle;
    }

    @Override
    public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
       this.resourceCallback= resourceCallback;
    }
}

现在您已经IdlingResource写了,您需要在正确的地方使用它吗?

用法

让我们跳过整个测试类的设置,只看一下测试用例的外观:

@Test
public void testSomeFragmentText() {
    mActivityTestRule.launchActivity(null);
   
    //创建空闲资源
    IdlingResource fragmentLoadedIdlingResource = new FragmentIdlingResource(mActivityTestRule.getActivity().getSupportFragmentManager(), SomeFragmentText.TAG);
    //注册空闲资源,以便意式浓缩咖啡等待它
    Espresso.registerIdlingResources(idlingResource1);
    onView(withId(R.id.txtHelloWorld)).check(matches(withText(helloWorldText)));

    //让我们自己清理
    Espresso.unregisterIdlingResources(fragmentLoadedIdlingResource);
}

与JUnit规则结合

这并不难;您还可以以JUnit测试规则的形式应用空闲资源。例如,假设您有一些包含Volley的SDK,并且希望Espresso等待它。您可以创建一个JUnit规则,而无需编写每个测试用例或将其应用到设置中,而只需编写:

@Rule
public final SDKIdlingRule mSdkIdlingRule = new SDKIdlingRule(SDKInstanceHolder.getInstance());

现在,因为这是一个示例,所以不要将其视为理所当然;这里的所有代码都是虚构的,仅用于演示目的:

public class SDKIdlingRule implements TestRule {
    //您编写要检查的空闲资源是否凌空空闲
    private VolleyIdlingResource mVolleyIdlingResource;
    //从排球请求您需要的队列以将其分配给空闲资源
    private RequestQueue mRequestQueue;

    //使用规则时,从SDK中提取请求队列
    public SDKIdlingRule(SDKClass sdkClass) {
        mRequestQueue = getVolleyRequestQueue(sdkClass);
    }

    private RequestQueue getVolleyRequestQueue(SDKClass sdkClass) {
        return sdkClass.getVolleyRequestQueue();
    }

    @Override
    public Statement apply(final Statement base, Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                //注册空闲资源
                mVolleyIdlingResource = new VolleyIdlingResource(mRequestQueue);
                Espresso.registerIdlingResources(mVolleyIdlingResource);
                try {
                    base.evaluate();
                } finally {
                    if (mVolleyIdlingResource != null) {
                        //测试完成后注销资源
                        Espresso.unregisterIdlingResources(mVolleyIdlingResource);
                    }
                }
            }
        };
    }
}