IdlingResource
閒置資源的力量在於不必等待應用程式的處理(網路,計算,動畫等)來完成 sleep()
,這會帶來瑕疵和/或延長測試執行時間。官方文件可以在這裡找到。
履行
實現 IdlingResource
介面時,你需要做三件事:
getName()
- 返回你的空閒資源的名稱。isIdleNow()
- 檢查你的 xyz 物件,操作等是否空閒。registerIdleTransitionCallback
(IdlingResource.ResourceCallback
callback) - 提供一個回撥,當你的物件轉換為空閒時你應該呼叫它。
現在,你應該建立自己的邏輯並確定應用程式何時處於空閒狀態,何時處於空閒狀態,因為這取決於應用程式。下面你會看到一個簡單的例子,只是為了說明它是如何工作的。線上還有其他示例,但特定的應用程式實現會帶來特定的空閒資源實現。
筆記
- 有一些谷歌的例子,他們把
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;
//resource callback you use when your activity transitions to idle
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() {
//simple check, if your fragment is added, then your app has became idle
boolean idle = (mFragmentManager.findFragmentByTag(mTag) != null);
if (idle) {
//IMPORTANT: make sure you call onTransitionToIdle
resourceCallback.onTransitionToIdle();
}
return idle;
}
@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
this.resourceCallback = resourceCallback;
}
}
現在你已經編寫了 IdlingResource
,你需要在某處使用它嗎?
用法
讓我們跳過整個測試類設定,看看測試用例的外觀如何:
@Test
public void testSomeFragmentText() {
mActivityTestRule.launchActivity(null);
//creating the idling resource
IdlingResource fragmentLoadedIdlingResource = new FragmentIdlingResource(mActivityTestRule.getActivity().getSupportFragmentManager(), SomeFragmentText.TAG);
//registering the idling resource so espresso waits for it
Espresso.registerIdlingResources(idlingResource1);
onView(withId(R.id.txtHelloWorld)).check(matches(withText(helloWorldText)));
//lets cleanup after ourselves
Espresso.unregisterIdlingResources(fragmentLoadedIdlingResource);
}
結合 JUnit 規則
這不難; 你還可以以 JUnit 測試規則的形式應用空閒資源。例如,假設你有一些包含 Volley 的 SDK,並且你希望 Espresso 等待它。你可以建立一個 JUnit 規則,而不是遍歷每個測試用例或在設定中應用它,而只需編寫:
@Rule
public final SDKIdlingRule mSdkIdlingRule = new SDKIdlingRule(SDKInstanceHolder.getInstance());
既然這是一個例子,不要把它視為理所當然; 這裡的所有程式碼都是虛構的,僅用於演示目的:
public class SDKIdlingRule implements TestRule {
//idling resource you wrote to check is volley idle or not
private VolleyIdlingResource mVolleyIdlingResource;
//request queue that you need from volley to give it to idling resource
private RequestQueue mRequestQueue;
//when using the rule extract the request queue from your 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 {
//registering idling resource
mVolleyIdlingResource = new VolleyIdlingResource(mRequestQueue);
Espresso.registerIdlingResources(mVolleyIdlingResource);
try {
base.evaluate();
} finally {
if (mVolleyIdlingResource != null) {
//deregister the resource when test finishes
Espresso.unregisterIdlingResources(mVolleyIdlingResource);
}
}
}
};
}
}