問題:
在做UI自動化測試時,偶爾會碰到 Toast 這種提示信息(如圖),通過Uiautomatorviewer 無法獲該類控件的信息。所以無法驗證,該條case不能實現。然后就沒然后了...
思考:
在《UiAutomator2.0 - 與AccessibilityService的關聯》實驗后,發現Toast提示信息所屬事件為 AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED
,依據《UiAutomator2.0 - 控件實現點擊操作原理》中的分析,那也可以模仿源碼監聽該事件啊!美滋滋~~
實現:
准備着手實現時,發現其他類的相關方法並沒公開,只有UiAutomation這個類公開了setOnAccessibilityEventListener方法(通過該方法進行監聽Toast)。突破口找到了,那么就從這個方法開始實現。
1、創建一個 VerifyToast類,代碼如下:
package com.testtoast;
import android.app.Notification;
import android.app.UiAutomation;
import android.os.Parcelable;
import android.support.test.InstrumentationRegistry;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
/**
* @author zzw
* Toast Validation Helper
*/
public class VerifyToast {
private static final String TAG = TestCase_FM.class.getSimpleName();
private static VerifyToast verifyToast = new VerifyToast();
private boolean isPass;
private VerifyToast(){}
public static VerifyToast getVerifyToast(){
return verifyToast;
}
public boolean getIsPass(){
return isPass;
}
public VerifyToast setIsPass(boolean isPass){
this.isPass = isPass;
return this;
}
/**
* Listen for toast prompts
* @param pck The package name of toast
* @param msg Toast info
*/
public void monitoringToast(final String pck, final String msg){
UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
uiAutomation.setOnAccessibilityEventListener(new UiAutomation.OnAccessibilityEventListener() {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if(event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED){
Log.d(TAG, "onAccessibilityEvent:"+
String.format("--pck: %s --msg: %s",getPackage(event),getMessage(event)));
isPass = pck.equals(getPackage(event)) && msg.equals(getMessage(event));
Log.d(TAG, "onAccessibilityEvent: isPass = "+ isPass);
}
}
});
}
// 獲取監聽的包名
private String getPackage(AccessibilityEvent event){
return (String) event.getPackageName();
}
// 獲取 Toast 信息
private String getMessage(AccessibilityEvent event){
String message = null;
Parcelable parcelable = event.getParcelableData();
if (!(parcelable instanceof Notification)) {
message = (String) event.getText().get(0);
}
return message;
}
}
2、測試用例中的調用
package com.testtoast;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiSelector;
import android.util.Log;
import com.zzw.commonutils.UiApps;
import com.zzw.tools.ScreenCap;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import static junit.framework.Assert.assertTrue;
/**
* @author zzw
* Test for Toast
*/
@RunWith(AndroidJUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestCase_FM {
private static final String TAG = TestCase_FM.class.getSimpleName();
private UiDevice device= UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
private String catchFail = "Catch_Pic";
@BeforeClass
public static void before(){
Log.d(TAG, "before: -----------------------------start-------------");
}
@Test
public void testCase_GetToast() throws Throwable {
VerifyToast verifyToast = VerifyToast.getVerifyToast();
String pck = "com.caf.fmradio";
String msg = "Please plug in a Headset to use FM Radio";
device.pressHome();
UiObject app= device.findObject(new UiSelector().text("FM Radio"));
Log.d(TAG, "testCase_GetToast: result == "+verifyToast.getIsPass());
verifyToast.setIsPass(false).monitoringToast(pck,msg);
try{
new UiApps().toOpenApp(app); //自己封裝打開app的方法
assertTrue("Toast prompt error", verifyToast.getIsPass());
}catch (Throwable e){
e.printStackTrace();
// 自己封裝的截圖方法
ScreenCap.takeScreenshotToPicturesDirPath(catchFail);
throw e;
}
Log.d(TAG, "testCase_GetToast: result == "+verifyToast.getIsPass());
}
}
注:在 adb shell uiautomator --help
中有這么一句
events: prints out accessibility events until terminated
那么在控制台也直觀的查看當前的Accessibility事件了,結果如圖: