[TOC]html
问题:在作UI自动化测试时,偶尔会碰到 Toast 这种提示信息(如图),经过Uiautomatorviewer 没法获该类控件的信息。因此没法验证,该条case不能实现。而后就没而后了... android
思考:在《UiAutomator2.0 - 与AccessibilityService的关联》实验后,发现Toast提示信息所属事件为 AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED
,依据《UiAutomator2.0 - 控件实现点击操做原理》中的分析,那也能够模仿源码监听该事件啊!美滋滋~~shell
实现:准备着手实现时,发现其余类的相关方法并没公开,只有UiAutomation这个类公开了setOnAccessibilityEventListener方法(经过该方法进行监听Toast)。突破口找到了,那么就从这个方法开始实现。
一、建立一个 VerifyToast类,代码以下:app
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; } }
二、测试用例中的调用ide
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 terminatedui
那么在控制台也直观的查看当前的Accessibility事件了,结果如图: this