最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

干貨|app自動(dòng)化測(cè)試之Appium 源碼修改定制分析

2022-10-21 10:42 作者:愛(ài)測(cè)軟件測(cè)試  | 我要投稿

Appium 是由 Node.js 來(lái)實(shí)現(xiàn)的 HTTP 服務(wù),它并不是一套全新的框架,而是將現(xiàn)有的優(yōu)秀的框架進(jìn)行了集成,在 Selenium WebDriver 協(xié)議(JsonWireProtocol/Restful web service)的基礎(chǔ)上增加了移動(dòng)端的支持,使 Appium 滿足多方面的需求。
官方提供更詳細(xì)的 Appium 結(jié)構(gòu)說(shuō)明:appium.io/docs/en/contr

Appium 框架結(jié)構(gòu)

Appium 是由多個(gè)子項(xiàng)目構(gòu)成的,github 訪問(wèn)如下圖:

Appium 由 Appium 以及其它的工作引擎包括:appium-xcuitest-driver、appium-android-driver、appium-ios-driver、appium-uiautomator2-server、appium-base-driver 等組成。下載 Appium 這個(gè)項(xiàng)目進(jìn)行分析,發(fā)現(xiàn) Appium 有著非常復(fù)雜的目錄結(jié)構(gòu),如下圖:

其中重要的目錄如下:

項(xiàng)目中有個(gè)文件 package.json ,這個(gè)文件是項(xiàng)目的描述文件。對(duì)項(xiàng)目或者模塊包的描述,比如項(xiàng)目名稱,項(xiàng)目版本,項(xiàng)目執(zhí)行入口文件,項(xiàng)目貢獻(xiàn)者等等。npm install命令會(huì)根據(jù)這個(gè)文件下載所有依賴模塊,查看這個(gè)文件可以看到如下的信息:

"dependencies": { ?

?"@babel/runtime": "^7.6.0", ?

??"appium-android-driver": "^4.20.0",

? ?"appium-base-driver": "^5.0.0", ??

?"appium-espresso-driver": "^1.0.0",?

? ?"appium-fake-driver": "^0.x", ??

?"appium-flutter-driver": "^0",?

? ?"appium-ios-driver": "4.x", ??

?"appium-mac-driver": "1.x",?

?? ?"appium-support": "2.x", ??

?"appium-tizen-driver": "^1.1.1-beta.4", ?

??"appium-uiautomator2-driver": "^1.37.1",?

? ?"appium-windows-driver": "1.x", ?

??"appium-xcuitest-driver": "^3.0.0", ?

?... ?

},

dependencies 表示此模塊依賴的模塊和版本信息。從這里面可以看到它依賴很多 driver ,比如 appium-android-driver、appium-base-driver、appium-espresso-driver、appium-ios-driver、appium-uiautomator2-driver 等等。下面我們會(huì)根據(jù) appium-uiautomator2-driver 重點(diǎn)對(duì) Android 測(cè)試驅(qū)動(dòng)的源碼進(jìn)行分析。

appium-uiautomator2-server

appium-uiautomator2-server 是針對(duì) UiAutomator V2 提供的服務(wù),是一個(gè)運(yùn)行在設(shè)備上的 Netty 服務(wù)器,用來(lái)監(jiān)聽(tīng)指令并執(zhí)行 UiAutomator V2 命令。

早期版本 Appium 通過(guò) appium-android-bootstrap 實(shí)現(xiàn)與 UiAutomator V1 的交互,UiAutomator2 修復(fù)了 UiAutomator V1 中遇到的大多數(shù)問(wèn)題,最重要的是實(shí)現(xiàn)了與 Android 系統(tǒng)更新的分離。

Appium 底層執(zhí)行 Android 測(cè)試真正的工作引擎是一個(gè) JAVA 項(xiàng)目 appium-uiautomator2-server??梢詫⑦@個(gè)項(xiàng)目克隆到本地,使用 Android Studio 工具或者其它的 JAVA 項(xiàng)目 IDE 工具打開(kāi)這個(gè)項(xiàng)目。

appium-uiautomator2-server啟動(dòng)

從 README 文件可以看到啟動(dòng)服務(wù)的方式:

Starting server

push both src and test apks to the device \?

and execute the instrumentation tests.?

?adb shell am instrument -w \?

io.appium.uiautomator2.server.test/\ androidx.test.runner.AndroidJUnitRunner

找到 AppiumUiAutomator2Server.java 這個(gè)文件,如下圖:

startServer( ) 方法就是它的啟動(dòng)入口函數(shù)。這個(gè)函數(shù)里面調(diào)用了 ServerInstrumentation 類里面的 startServer( ) 方法。如下圖:

startServer( ) 方法會(huì)創(chuàng)建一個(gè)新的線程來(lái)處理一系列的邏輯。

AppiumServlet解析

AppiumServlet 是一個(gè)典型 HTTP 請(qǐng)求的處理協(xié)議。使用 AppiumServlet 來(lái)管理請(qǐng)求,并將 Driver 發(fā)過(guò)來(lái)的請(qǐng)求轉(zhuǎn)發(fā)給對(duì)應(yīng) RequestHandler,它會(huì)監(jiān)聽(tīng)下面的 URL

...?

register(postHandler, new FindElement(“/wd/hub/session/:sessionId/element”)); register(postHandler, new FindElements(“/wd/hub/session/:sessionId/elements”)); ...

當(dāng)這些 URL 有請(qǐng)求過(guò)來(lái),AppiumServlet 會(huì)對(duì)它執(zhí)行相關(guān)的處理。比如查找元素、輸入、點(diǎn)擊等操作。以查找元素為例,實(shí)現(xiàn)類里可以看到下面一段代碼:

... final String method = payload.getString("strategy"); final String selector = payload.getString("selector"); final String contextId = payload.getString("context"); ...

通過(guò)這三個(gè)屬性“strategy”、“selector”、“context” 來(lái)定位元素。在 Appium 對(duì)應(yīng)的日志中可以看到這個(gè)操作。

2020-04-08 10:42:37:928 [HTTP] --> POST /wd/hub/session/f99fe38b-445b-45d2-bda0-79bf12e8910e/element 2020-04-08 10:42:37:929 [HTTP] {"using":"xpath",\ "value":"//*[@text=\"交易\"]"} 2020-04-08 10:42:37:930 [W3C (f99fe38b)] Calling \ AppiumDriver.findElement() with args: ["xpath","//*[@text=\"交易\"]","f99fe38b-445b-45d2-bda0-79bf12e8910e"] ... 2020-04-08 10:42:37:931 [WD Proxy] Matched '/element' to \ command name 'findElement' 2020-04-08 10:42:37:932 [WD Proxy] Proxying [POST /element] to \ [POST http://127.0.0.1:8200/wd/hub/session/\ 0314d14d-b580-4098-a559-602559cd7277/element] \ with body: {"strategy":"xpath","selector":\ "//*[@text=\"交易\"]","context":"","multiple":false} ... 2020-04-08 10:42:39:518 [W3C (f99fe38b)] Responding \ to client with driver.findElement() \ result: {"element-6066-11e4-a52e-4f735466cecf":\ "c57c34b7-7665-4234-ac08-de11641c8f56",\ "ELEMENT":"c57c34b7-7665-4234-ac08-de11641c8f56"} 2020-04-08 10:42:39:519 [HTTP] <-- POST /wd/hub/session/f99fe38b-445b-45d2-bda0-79bf12e8910e/element 200 1590 ms - 137

上面代碼,定位元素的時(shí)候會(huì)發(fā)送一個(gè) POST 請(qǐng)求,Appium 會(huì)把請(qǐng)求轉(zhuǎn)為 UiAutomatorV2 的定位,然后轉(zhuǎn)發(fā)給 UiAutomatorV2。

擴(kuò)展功能

在 FindElement.java 中實(shí)現(xiàn)了 findElement( ) 方法,如下圖:

private Object findElement(By by) throws UiAutomator2Exception, UiObjectNotFoundException { ? ? ? ?refreshAccessibilityCache(); ? ? ? ?if (by instanceof ById) { ? ? ? ? ? ?String locator = rewriteIdLocator((ById) by); ? ? ? ? ? ?return CustomUiDevice.getInstance().findObject(androidx.test.uiautomator.By.res(locator)); ? ? ? ?} else if (by instanceof By.ByAccessibilityId) { ? ? ? ? ? ?return CustomUiDevice.getInstance().findObject(androidx.test.uiautomator.By.desc(by.getElementLocator())); ? ? ? ?} else if (by instanceof ByClass) { ? ? ? ? ? ?return CustomUiDevice.getInstance().findObject(androidx.test.uiautomator.By.clazz(by.getElementLocator())); ? ? ? ?} else if (by instanceof By.ByXPath) { ? ? ? ? ? ?final NodeInfoList matchedNodes = getXPathNodeMatch(by.getElementLocator(), null, false); ? ? ? ? ? ?if (matchedNodes.isEmpty()) { ? ? ? ? ? ? ? ?throw new ElementNotFoundException(); ? ? ? ? ? ?} ? ? ? ? ? ?return CustomUiDevice.getInstance().findObject(matchedNodes); ? ? ? ?} ? ? ? ?... ? ?}

findElement( ) 方法具體的提供了 ById、ByAccessibilityId、ByClass、ByXpath 等方法,可以擴(kuò)展這部分功能,如果將來(lái)引申出來(lái)一些功能,比如想要通過(guò)圖片、AI 定位元素,可以在上面的 findElement( ) 方法里面添加 else if (by instanceof ByAI) 方法,來(lái)創(chuàng)建新類型ByAI并且增加功能的實(shí)現(xiàn)。比如未來(lái)新增了 AI 來(lái)定位元素的功能,可以使用 AI 的插件(基于 nodejs 封裝的一個(gè)插件)test.ai 插件(https://github.com/testdotai/appium-classifier-plugin)
用法:

driver.find_element('-custom', 'ai:cart');

項(xiàng)目構(gòu)建與apk安裝

完成代碼的修改之后需要重新編譯生成相應(yīng)的 apk 文件,并放到 Appium 對(duì)應(yīng)的目錄下。

Android Studio → 項(xiàng)目 Gradle → appium-uiautomator2-server-master → Task-other 下。
分別雙擊 assembleServerDebug 與 assembleServerDebugAndroidTest 即可完成編譯,編譯完成會(huì)在目錄下生成對(duì)應(yīng)的兩個(gè) apk 文件。

  • assembleServerDebugAndroidTest.apk

構(gòu)建后 apk 所在目錄:app/build/outputs/apk/androidTest/server/debug/appium-uiautomator2-server-debug-androidTest.apk 這個(gè) apk 是個(gè)驅(qū)動(dòng)模塊,負(fù)責(zé)創(chuàng)建會(huì)話,安裝 UiAutomator2-server.apk 到設(shè)備上,開(kāi)啟 Netty 服務(wù)。

  • assembleServerDebug

構(gòu)建后 apk 所在目錄:app/build/outputs/apk/server/debug/appium-uiautomator2-server-v4.5.5.apk,這是服務(wù)器模塊,當(dāng)驅(qū)動(dòng)模塊初始化完畢,服務(wù)器就會(huì)監(jiān)聽(tīng) PC 端 Appium 發(fā)送過(guò)來(lái)的請(qǐng)求,將請(qǐng)求發(fā)送給真正底層的 UiAutomator2。
另外,也可以使用命令來(lái)進(jìn)行構(gòu)建:

gradle clean assembleE2ETestDebug assembleE2ETestDebugAndroidTest

將編譯完成的 APK,覆蓋 Appium 目錄下對(duì)應(yīng)的 APK 文件。需要先使用命令查找 Appium 安裝目錄下的 Uiautomator server 對(duì)應(yīng)的 APK,MacOS 操作命令如下:

find /usr/local/lib/node_modules/appium -name "*uiautomator*.apk"

使用上面的命令會(huì)發(fā)現(xiàn)關(guān)于 Uiautomator 的兩個(gè) apk 文件,如下:

$ find /usr/local/lib/node_modules/appium -name \?

"*uiautomator*.apk" /usr/local/lib/node_modules/appium/node_modules\ /appium-uiautomator2-server/apks/\?

appium-uiautomator2-server-v4.5.5.apk

/usr/local/lib/node_modules/appium/\?

node_modules/appium-uiautomator2-server\?

/apks/appium-uiautomator2-server-debug-androidTest.apk

將編譯好的 APK 替換這個(gè)目錄下的 APK 即可。
客戶端會(huì)傳遞 Desired Capabilities 給 Appium Server 創(chuàng)建一個(gè)會(huì)話,Appium Server 會(huì)調(diào)用 appium-uiautomator2-driver 同時(shí)將 UiAutomator2 Server 的兩個(gè) apk 安裝到測(cè)試設(shè)備上(也就是上面生成的兩個(gè) apk 文件)。


干貨|app自動(dòng)化測(cè)試之Appium 源碼修改定制分析的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
新安县| 江山市| 炉霍县| 安达市| 江华| 乐山市| 大冶市| 华安县| 霍州市| 桃园市| 祥云县| 海宁市| 安康市| 大余县| 化隆| 新密市| 平谷区| 遂溪县| 门头沟区| 勃利县| 平昌县| 吴桥县| 衡阳县| 巴林右旗| 大化| 通山县| 南澳县| 西乌| 农安县| 岳池县| 桦甸市| 土默特左旗| 蚌埠市| 浦北县| 巧家县| 子洲县| 苗栗县| 陕西省| 资源县| 忻城县| 会理县|