appium ,selenium ,webdriver 運行原理與機制
requests底層原理
http://www.lxweimin.com/p/643805a92fde
api.py實現了基本的對外接口,即get,post,delete等http方法名命名的一系列函數,經常在代碼中看到有人將這些方法又封裝了一個通用函數, 實際上這些方法就是通過調用一個更為通用的request方法來實現的:
defrequest(method, url, **kwargs):withsessions.Session()assession:returnsession.request(method=method, url=url, **kwargs)
可以看到這個request方法的是通過sessions.Session()來實現的,一直只知道requests中的session是用來維持長鏈接的,但其實requests提供的基本http方法底層也是通過session實現
的,只不過每一個基本方法調用完,這個session就結束了,其相關的資源(包括連接,cookies等)也就
釋放了。
session.py實現了整個Session類, 以及一些session功能依賴的外部方法和類(比如其中merge_setting函數實現了將每個請求的參數和session參數的合并,從而可以讓一個session中所有請求共用的參數只需要在session中設置,而每個請求可以設置自己特有的參數,同時不影響其他請求,而SessionRedirectMixin類則實現了redirect相關的一些邏輯,這部分邏輯是session必須的,但是又不是session的核心功能,因此通過Mixin類來實現),Session類也暴露了以http方法命名的一系列對外接口,session最核心的功能就是保持會話,因此在prepare_request方法中實現了將session中的headers,cookies,auth等關鍵參數和每個request的這些參數合并,組合出完整的http請求,最終通過send方法發送出去send方法拿到http請求響應以后,又會將服務端設置的cookies等信息保存在session中,以待下一個request使用。send方法最終發送請求是根據請求schema確定一個實現了BaseAdapter接口的對象
?做測試開發的童鞋都知道,UI自動化你繞不開selenium, webdrvier, appium框架,那么這三者之間有什么關聯,它們的原理是什么呢?
簡單來說就是:
Selenium2? 將瀏覽器原生的API封裝成WebDriver API ,webdriver 是基于 http協議的;
appium是基于 webdriver 協議添加對移動設備自動化api擴展而成的,基于tcp/ip協議(使用了socket接口)
推論: 凡是牽扯到客戶端和服務器交互的,都有Http 協議
凡是牽扯到移動端社保的,都有tcp/ip 協議(封裝成socket接口)
面試的時候如何口述Selenium 原理?
Selenium 是將各個瀏覽器的API封裝成" Selenium自己設計定義的協議,名字叫做The WebDriver Wire Protocol " 的webdriver API?
操作層面:
1、測試人員編寫UI自動化測試腳本(java,python等等),運行腳本后,程序會打開指定的webdriver瀏覽器
2. webdriver瀏覽器作為一個remote-server 接受腳本的命令,同時webservice會打開一個端口:http://localhost:46350? 瀏覽器則會監聽這個端口
2、webservice會將腳本語言翻譯成json格式傳遞給瀏覽器執行操作命令
邏輯層面:
1、測試人員執行測試腳本后,就創建了一個session, 通過http 請求向webservice發送了restfull的請求。
2、webservice翻譯restfull的請求為瀏覽器能懂的腳本,然后接受腳本執行結果。
3、webservice將結果進行封裝--json 給到客戶端client/測試腳本 ,然后client就知道操作是否成功,同時測試也可以進行校驗了。
口述appium的原理:
appium-IOS 和安卓都差不多,有細小差別,分PC和手機兩塊講:
1、首先是PC端, 測試人員執行測試腳本(java,python等腳本)通過appium client 轉換為json格式傳遞給appium server
2、 appiumserver 啟動了一個監聽端口例如4724, 同時向手機端adb push 一個bootstrap.jar/bootstrap.js 的腳本,手機端通過該腳本同時監聽端口4724
3、PC和手機端就通過這個端口實現了通信和交互,基于socket通信(一個封裝了TCP/IP協議的接口)
4、手機端通過該端口傳輸的命令執行APP, bootstrap里面封裝了安卓和蘋果的自動化測試框架UIautomator(低版本的安卓是instrumentation?) 執行相應的命令
5、執行完操作后通過端口返回給PC端,PC端根據返回結果 json 做校驗,同時也知道了操作是否執行成功
所以UI自動化的底層還是webdriver ,它是基于HTTP協議的,那么HTTP的原理是什么? 長連接短連接是什么意思,下個博客總結:
Selenium2?
Selenium是一個用于Web應用程序測試的工具,支持多平臺、多瀏覽器、多語言去實現自動化測試,Selenium2將瀏覽器原生的API封裝成WebDriver API,可以直接操作瀏覽器頁面里的元素,甚至操作瀏覽器本身(截屏,窗口大小,啟動,關閉,安裝插件,配置證書之類的),所以就像真正的用戶在操作一樣。
Webdriver的一個簡單的架構圖,如下圖所示:
WebDriver的工作原理圖:
在我們new一個WebDriver的過程:
1. Selenium首先會確認瀏覽器的native component是否存在可用而且版本匹配(selenium版本對應到 不同的瀏覽器driver版本)。
2.在目標瀏覽器里啟動一整套Web Service(實際上就是瀏覽器廠商提供的driver, 比如IEDriver, ChromeDriver,它們都實現了WebDriver's?wire protocol),
3.這套Web Service使用了Selenium自己設計定義的協議,名字叫做The WebDriver Wire Protocol。這套協議非常之強大,幾乎可以操作瀏覽器做任何事情,包括打 開、關閉、最大化、最小化、元素定位、元素點擊、上傳文件等等等等。
WebDriver Wire協議是通用的,也就是說不管是FirefoxDriver還是ChromeDriver,啟動之后都會在某一個端口啟動基于這套協議的Web Service。例如FirefoxDriver初始化成功之后,默認會從http://localhost:7055開始,而ChromeDriver則大概是http://localhost:46350之類的。接下來,我們調用WebDriver的任何API,都需要借助一個ComandExecutor發送一個命令,實際上是一個HTTP request給監聽端口上的Web Service。在我們的HTTP request的body中,會以WebDriver Wire協議規定的JSON格式的字符串來告訴Selenium我們希望瀏覽器接下來做什么事情。
可以更通俗的理解:由于客戶端腳本(java, python, ruby)不能直接與瀏覽器通信,這時候可以把WebService當做一個翻譯器,它可以把客戶端代碼翻譯成瀏覽器可以識別的代碼(比如js).客戶端(也就是測試腳本)創建1個session,在該session中通過http請求向WebService發送restful的請求,WebService翻譯成瀏覽器懂得腳本傳給瀏覽器,瀏覽器把執行的結果返回給WebService,WebService把返回的結果做了一些封裝(一般都是json格式),然后返回給client,根據返回值就能判斷對瀏覽器的操作是不是執行成功
舉個實際的例子:
WebDriver diver = new FirefoxDriver();
driver.get("http://google.com");
在執行?driver.get("http://google.com");??這句代碼時,client也就是我們的測試代碼向Web Service(remote server)發送了如下的請求:
POST session/285b12e4-2b8a-4fe6-90e1-c35cba245956/url
post_data {"url":"http://google.com"}?
通過post的方式請求localhost:port/hub/session/session_id/url地址,請求瀏覽器完成跳轉url的操作。
如果上述請求是可接受的,或者說Web Service是實現了這個接口,那么Web Service會跳轉到該post data包含的url,并返回如下的response
{"name":"get","sessionId":"285b12e4-2b8a-4fe6-90e1-c35cba245956","status":0,"value":""}
該response中包含如下信息
name:Web Service端的實現的方法的名稱,這里是get,表示跳轉到指定url;
sessionId:當前session的id;
status:請求執行的狀態碼,非0表示未正確執行,這里是0,表示一切ok不必擔心;
value:請求的返回值,這里返回值為空,如果client調用title接口,則該值應該是當前頁面的title;
如果client發送的請求是定位某個特定的頁面元素,則response的返回值可能是這樣的:
{"name":"findElement","sessionId":"285b12e4-2b8a-4fe6-90e1-c35cba245956","status":0,"value":{"ELEMENT":"{2192893e-f260-44c4-bdf6-7aad3c919739}"}}
name,sessionId,status跟上面的例子是差不多的,區別是該請求的返回值是ELEMENT:{2192893e-f260-44c4-bdf6-7aad3c919739},表示定位到元素的id,通過該id,client可以發送如click之類的請求與server端進行交互。
APPIUM運行原理:
Appium是 c/s模式的
appium是基于 webdriver 協議添加對移動設備自化api擴展而成的
webdriver 是基于 http協議的,第一連接會建立個 session 會話,并通過 post發送一個 json 告知服務端相關測試信息
IOS 原理圖
appium ios封裝了 封裝了 封裝了 apple 的 Instruments 框架,主要用了 Instrument里的 UIAutomation(Apple? 的自動化測試框架),然后在設備中注入? bootstrap.js?進 行監 聽。
Client ent是我們編寫的 webdriver腳本 ,中間是 appium啟動 server (默認監聽 4723 端口 ),
appium server? 調用 instruments.js啟動一個 socket server ,同時分出一個 子進程運?instruments.app 將 bootstrap.js(一個 UIAutomation 腳本)注 ?入到 devices?于和外界進行交 。
最后 Bootstrap.js將執行的結果返回給 將執行的結果返回給 appium server? ,appium server再將結果返回給 appium client 。
Android原理圖
4.2 以后是基于 uiautomator框架實現查找注入事件的, 框架實現查找注入事件的,框架實現查找注入事件的, 4.2 以前則是 instrumentation i框架的,并封裝成一個叫 Selendroid 這玩意提供服務
Client ent是我們編寫的 webdriver 腳本。中間是 appium啟動 server? (默認監聽? 4723 端口 ),
appium server? 會把請求轉發給中間件 會把請求轉發給中間件 Bootstrap.jar? ,它是用java寫的,安裝在手機上 .Bootstrap監聽 4723端口并接收appium? 的命令,最終通過調用 UiAutomator 的命令來實現。
Bootstrap將執行的結果返回給返回給 appium server 。
Appiumserver再將結果返回給 client端(PC)。