轉載: http://blog.csdn.net/five3/article/details/9428655
Selenium-Grid版本
selenium-grid分為版本1和版本2,其實它的2個版本並不是和selenium的版本1和2相對應發布的[即selenium-grid2的發布比selenium2要晚一點]。不過幸運的是現在的selenium-grid2基本能支持selenium2的所有功能了。
selenium雖然分1和2,但其實原理和基本工作方式都是一樣的。只是版本2同時支持selenium1和selenium2兩種協議,並且在一些小的功能和易用性上進行了優化。比如:指定測試平台的方式;以下未作特殊說明的Selenium-Grid均為通用。
Selenium1工作原理
selenium1中除了使用selenium-core以外,進行自動化測試時都需要使用selenium-RC來作為代理[不管是本機還是遠程],目的是為了解決同源問題;而造成同源問題的原因是因為selenium1中是使用Javascript來驅動測試執行的【瀏覽器由於安全問題不允許不同域之間的JS調用,即非同源不可調用;而selenium1中的工作方式就是在宿主頁面注入JS並且通過調用JS來執行測試操作的,所以就設計到同源問題】。所以為了達成目的,其解決方案就有2種:
1、使用selenium-core:
selenium-core是一組js庫,用來驅動瀏覽器操作的所有庫文件都在這里,整個selenium1可以認為核心組件就是這個selenium-core;而使用selenium-core的方式就是在被測試站點程序的源碼里把selenium-core中的所有js庫直接添加到頁面里,這樣頁面正常加載的同時也會把selenium-core加載下來,並且天生就是同源的。 2、使用selenium-RC:
RC是一個http代理程序,用來注入到瀏覽器和被測web程序之間,這樣瀏覽器所有的請求和接收的內容都會通過RC;RC會把瀏覽器的請求發送給真實的web程序,而在接收到web程序的響應內容時,並沒有把內容原原本本的返回給瀏覽器客戶端,而是把包含selenium-core的內容注入到響應內容中去,然后才發送響應內容給瀏覽器,這樣就通過欺騙的方式讓瀏覽器認為selenium1的驅動類庫同樣是同源的。
Selenium2工作原理
selenium2中因為使用的webdriver,這個技術不是靠js驅動的,而是直接調用瀏覽器的原生態接口驅動的。所以就沒有同源問題,也就不需要使用RC來執行本地腳本了【當然缺點就是並不是所有的瀏覽器都有提供很好的驅動支持,但JS卻是所有瀏覽器都通用的】。所以selenium2中執行本地腳本的方式是:通過本地webdriver驅動直接調用本地瀏覽器接口就完事了。在本地調用本地的代碼是這樣的:
import org.openqa.selenium.*; import org.openqa.selenium.firefox.*; WebDriver wd = new FirefoxDriver(); wd.doSomething()
但有時候並總是只執行本地測試的腳本,有時候可能需要在本地調用遠程的環境來執行測試,【比如:因為測試環境覆蓋原因】此時就需要一個類似selenium1中的RC來承擔這個任務,也就是selenium2中的selenium-server。selenium-server支持接收遠程腳本的調用命令,然后操作其宿主機上的瀏覽器來到遠程執行測試的任務。當然selenium-server為了兼容selenium1的腳本,它同樣也支持selniumRC所支持的功能【即能接收selenium1的調用命令】。在本地調用遠程機器執行測試的代碼是這樣的:
import org.openqa.selenium.*; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.remote.DesiredCapabilities; DesiredCapabilities ieDesiredcap = DesiredCapabilities.internetExplorer(); WebDriver wd = new RemoteDriver("http://localhost:4444/wd/hub", ieDesiredcap); wd.doSomething()
但是在運行這段代碼之前,要先啟動Selenium-Server;啟動命令為:
java -jar selenium-server-standalone-x.xx.x.jar
調用selenium-server對應的結構圖:
Selenium-Grid工作原理
到此為止,其實還沒有提到selenium-grid,因為到目前為止我們還沒有需求說同時覆蓋多個平台和瀏覽器,而selenium-grid在這種情況下就會體現出其作用來。selenium-grid是用於設計幫助我們進行分布式測試的工具,其整個結構是由一個hub節點和若干個代理節點組成。hub用來管理各個代理節點的注冊和狀態信息,並且接受遠程客戶端代碼的請求調用,然后把請求的命令再轉發給代理節點來執行。使用selenium-grid遠程執行測試的代碼與直接調用Selenium-Server是一樣的[只是環境啟動的方式不一樣,需要同時啟動一個hub和至少一個node]:
java -jar selenium-server-standalone-x.xx.x.jar -role hub java -jar selenium-server-standalone-x.xx.x.jar -role node
上面是啟動一個hub和一個node,若是同一台機器要啟動多個node則要注意端口分配問題,可以這樣來啟動多個node:
java -jar selenium-server-standalone-x.xx.x.jar -role node -port 5555 java -jar selenium-server-standalone-x.xx.x.jar -role node -port 5556 java -jar selenium-server-standalone-x.xx.x.jar -role node -port 5557
調用Selenium-Grid的基本結構圖如下: 上面是使用selenium-grid的一種普通方式,僅僅使用了其支持的分布式執行的功能,即當你同時需要測試用例比較多時,可以平行的執行這些用例進而縮短測試總耗時;除此之外,selenium-grid還支持一種更友好的功能,即可以根據你用例中啟動測試的類型來相應的把用例轉發給符合匹配要求的測試代理。例如你的用例中指定了要在Liunux上FF的3.6版本進行測試,那么selenium-grid會自動匹配注冊信息為Linux、且安裝了FF3.6的代理節點,如果匹配成功則轉發測試請求,如果失敗則拒絕請求。使用selenium-grid的遠程兼容性測試的代碼同上。其調用的基本結構圖如下:
了解了selenium-grid的基本結構,再來看看selenium-grid通信的原理。假設現在我們有這樣一個場景:[一個測試請求客戶端、一個hub節點、一個Windows+ie代理、一個linux+FF代理、一個Mac+Safari代理、一個任意平台下的Chrome代理]。其分布圖如下:
測試的代碼如下:
import org.openqa.selenium.*; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.remote.DesiredCapabilities; //test01: 只匹配Windows下的ie來執行此用例,版本不限;多個版本匹配成功時優先級暫未知 DesiredCapabilities aDesiredcap = DesiredCapabilities(); aDesiredcap.setBrowserName("internet explorer") aDesiredcap.setVersion("") aDesiredcap.setPlatform(Platform.WINDOWS) WebDriver wd = new RemoteDriver("http://localhost:4444/wd/hub", aDesiredcap); wd.doSomething() //test02: 只匹配linix下的firefox的版本為22的瀏覽器執行用例; DesiredCapabilities aDesiredcap = DesiredCapabilities("firefox", "22", Platform.LINUX); WebDriver wd = new RemoteDriver("http://localhost:4444/wd/hub", aDesiredcap); wd.doSomething() //test03: 只匹配MAC下的safari瀏覽器執行,版本不限 DesiredCapabilities aDesiredcap = DesiredCapabilities.safari(); aDesiredcap.setPlatform(Platform.MAC) WebDriver wd = new RemoteDriver("http://localhost:4444/wd/hub", aDesiredcap); wd.doSomething() //test04: 只匹配chrome瀏覽器,任意平台,任意版本 DesiredCapabilities aDesiredcap = DesiredCapabilities.chrome(); aDesiredcap.setPlatform(Platform.ANY) WebDriver wd = new RemoteDriver("http://localhost:4444/wd/hub", aDesiredcap); wd.doSomething()
那么整個測試執行的過程大概是這樣的。首先我們在測試請求機上執行測試代碼,代碼中測試啟動方式為遠程調用;
WebDriver wd = new RemoteDriver("http://localhost:4444/wd/hub", aDesiredcap);
此時測試腳本就會根據啟動參數連接hub節點,這里的連接信息為
http://localhost:4444/wd/hub
連接到hub成功后,會在hub上注冊一個session信息;[后面再與hub通信時就會帶上這個session信息,告訴hub我之前來過,並且之前是被分配到哪個代理節點上執行過測試]
hub在接受初始化請求時會根據請求的類型來匹配所有代理,並確定是否有符合規則的代理;
如果匹配失敗了就會拒絕該初始請求;如果匹配成功則通知對應代理節點進行對應的初始化操作,這里是啟動XX,並記錄瀏覽器的注冊session,最后發回給hub端;
hub端接收到代理端起的完成后的session信息后,在hub中同樣要記錄session並返回給測試請求端,[session中會保存匹配到的代理信息]
在初始化請求成功之后,測試請求端會繼續發送下一條測試命令,這里的命令是:
wd.doSomething()
此命令會同樣被發送給hub,當然是帶上session信息的;
hub接收到帶有session的請求命令時,會查詢session的信息,得知session中對應的代理后就把請求的命令給轉發給該代理;
代理在接收到hub發送過來的測試命令后,同樣查詢其session信息,並根據session信息操作與之對應的瀏覽器以執行測試;
測試完成后會通知hub執行結果,hub再轉發給測試請求端,測試請求端根據的返回信息來決定接下來的執行流程;
最后測試結束后,通知hub關閉瀏覽器進程,同時清除對應的session信息。
由selenium-grid的原理可以得知
通過selenium-grid執行遠程操作時,並不需要遠程機器上有測試腳本;但是遠程機器上必須安裝了對應的webdriver程序[可以直接放在環境變量的目錄里即可],當然了,還得需要正確的啟動了代理程序