引言
在移動應用自動化測試中,??混合應用(Hybrid App)?? 和多窗口場景(如分屏、彈窗、多
WebView)的處理一直是技術難點。Appium 的enableMultiWindows
參數為這類場景提供了關鍵支持,但在實際使用中常因配置不當引發問題。
遇到的問題
起初在測試一個期貨交易類APP時,訂單發送后會有成交回報,在app的上方顯示。這個提示彈出框無法被appium獲取,獲取page souce XML結構時無法找到這個元素。其實這就是因為在Appium初始化driver時,沒有把這個參數設置成True,導致,這部分的元素XML結構不可見,所以無法定位,進行成交回報驗證和下一步操作。
解決方案
- 可以在Appium初始化時設置 把參數
"enableMultiWindows": True
設置成True
caps = {"platformName": "Android","deviceName": "emulator-5554","app": "/path/to/app.apk","automationName": "UiAutomator2", # 必須使用 UiAutomator2"enableMultiWindows": True # 啟用多窗口支持
}
- 但是我們使用的時測試平臺,沒有底層的初始話driver的操作,就不能在初始的時候去操作這個參數,所以就研究怎么在運行時去修改Appium的參數。其實Appium的代碼對外暴露的有修改設置的接口
driver.setSetting(Setting.WAIT_FOR_IDLE_TIMEOUT,60);
,但是這個Setting的類型時一個Enum類型,在它的源碼中能看到有以下幾種
IGNORE_UNIMPORTANT_VIEWS("ignoreUnimportantViews"),WAIT_FOR_IDLE_TIMEOUT("waitForIdleTimeout"),WAIT_FOR_SELECTOR_TIMEOUT("waitForSelectorTimeout"),WAIT_SCROLL_ACKNOWLEDGMENT_TIMEOUT("scrollAcknowledgmentTimeout"),WAIT_ACTION_ACKNOWLEDGMENT_TIMEOUT("actionAcknowledgmentTimeout"),KEY_INJECTION_DELAY("keyInjectionDelay"),NATIVE_WEB_TAP("nativeWebTap"),IMAGE_MATCH_THRESHOLD("imageMatchThreshold"),FIX_IMAGE_FIND_SCREENSHOT_DIMENSIONS("fixImageFindScreenshotDims"),FIX_IMAGE_TEMPLATE_SIZE("fixImageTemplateSize"),CHECK_IMAGE_ELEMENT_STALENESS("checkForImageElementStaleness"),UPDATE_IMAGE_ELEMENT_POSITION("autoUpdateImageElementPosition"),NORMALIZE_TAG_NAMES("normalizeTagNames"),IMAGE_ELEMENT_TAP_STRATEGY("imageElementTapStrategy");
其實是沒有我們想要的enableMultiWindows這個參數。所以我們接著看setSetting 的底層方法
public interface HasSettings extends ExecutesMethod {default void setSetting(Setting setting, Object value) {CommandExecutionHelper.execute(this, MobileCommand.setSettingsCommand(setting, value));}default Map<String, Object> getSettings() {Map.Entry<String, Map<String, ?>> keyValuePair = MobileCommand.getSettingsCommand();Response response = this.execute((String)keyValuePair.getKey(), (Map)keyValuePair.getValue());return ImmutableMap.builder().putAll((Map)Map.class.cast(response.getValue())).build();}
}
傳進來的setting是在這里使用的MobileCommand.setSettingsCommand(setting, value)
所接著看源碼,看看能否自己構造一個,看下setSettingsCommand
public static Map.Entry<String, Map<String, ?>> setSettingsCommand(Setting setting, Object value) {return new AbstractMap.SimpleEntry(SET_SETTINGS, prepareArguments((String)"settings", (Object)prepareArguments(setting.toString(), value)));}
可以看到(Object)prepareArguments(setting.toString(), value)
其實就是把enum的setting給轉成了string,所以我們完全可以自己傳進去一個enableMultiWindows
,并且把value也設置成true
, 這樣手動生成一個AbstractMap.SimpleEntry
就行了。
所以修改完成的代碼就是
CommandExecutionHelper.execute(driver,new AbstractMap.SimpleEntry<>("setSettings", prepareArguments((String)"settings", (Object)prepareArguments("enableMultiWindows", true))));
在測試代碼中執行這一行,就能解決沒有得到彈窗XML元素的問題。