一、Selenium Grid簡介
Selenium Grid組件專門用於遠程分佈式測試或併發測試。使用此組件能夠在一臺計算機上給多臺計算機(不一樣操做系統和不一樣版本瀏覽器環境)分發多個測試用例從而併發執行,
大大提升了測試用例的執行效率,基本知足大型項目自動化測試的時限要求和兼容性要求。
Selenium Grid使用Hub和Node模式,一臺計算機做爲Hub(管理中心)管理其餘多個Node(節點)計算機,Hub負責將測試用例分發給多臺Node計算機執行,並收集多臺Node計算機執行結果的報告,彙總後提交一份總的測試報告。
Hub:
>在分佈式測試模式中,只能有一臺做爲Hub的計算機
>Hub負責管理測試腳本,並負責發送腳本給其餘Node節點
>全部的Node節點計算機必須先在做爲Hub的計算機中進行註冊,註冊成功後再和Hub計算機通訊,Node節點計算機會告之Hub本身的相關信息,例如,Node節點的操做系統和瀏覽器相關版本。
Node:
>在分佈式測試模式中,能夠有一個或多個Node節點
>Node節點會打開本地的瀏覽器完成測試任務並返回測試結果給Hub
>Noel節點的操做系統和瀏覽器版本無需和Hub保持一致
>在Node節點上能夠同時打開多個瀏覽器並行執行測試任務java
二、分佈式自動化測試環境準備
(1)下載 JDK 1.8安裝文件(最好從官網下載)
(2)安裝JDK
(3)配置環境變量(1.8後的JDK會自動添加環境變量)
(4)在CMD中輸入java -version命令後回車,顯示出java信息,不報錯說明安裝成功node
三、Selenium Grid的使用方法
(1)遠程調用Firefox瀏覽器進行自動化測試(其餘瀏覽器同理)
具體步驟以下:
1)找兩臺WIndows系統的計算機A和B,A計算機做爲Hub,B計算機做爲Node(若是沒有能夠用本機即做Hub又做Node)
2)兩臺計算機均訪問http://www.seleniumhq.org/download,單擊「Selenium Standalone Server」下的「Download Version x.x.x」進行下載,並保存在兩臺計算機的存放Webdriver驅動的目錄中(如D盤根目錄)
3)在機器A上打開CMD窗口,並當前工做目錄切換到D盤根目錄,而後執行以下語句:
java -jar selenium-server-standalone-3.141.59.jar -role hub (不報錯即成功)
-role hub : 啓動一個Hub服務,做爲分佈式管理中心,等待webdriver客戶端進行註冊和請求,默認接收註冊的地址爲:http://localhost:4444/grid/register,默認啓動端口爲4444
4)在機器A(假如Ip地址爲192.168.1.123)中的Firefox瀏覽器(其餘瀏覽器也能夠)地址欄中訪問http://localhost:4444/grid/console,若是訪問的網頁中顯示出「view config」的連接,表示Hub已經成功啓動
5)在機器B(假如Ip地址爲192.168.1.124)中打開CMD窗口,將當前工做目錄D盤根目錄(即selenium-server-standalone-3.141.59.jar和Webdriver驅動所在目錄),輸入以下命令:
運行Firefox:
java -jar selenium-server-standalone-3.141.59.jar -role webdriver -hub http://192.168.31.94:4444/grid/register-Dwebdriver.firefox.driver="D:\geckodriver.exe" -port 6666 -maxSession 5 -browser browserName="firefox",maxInstances=5
運行Chrome:
java -jar selenium-server-standalone-3.141.59.jar -role webdriver -hub http://192.168.31.94:4444/grid/register-Dwebdriver.chrome.driver="D:\chromedriver.exe" -port 6666 -maxSession 5 -browser browserName="chrome",maxInstances=5
運行IE:
java -jar selenium-server-standalone-3.141.59.jar -role webdriver -hub http://192.168.31.94:4444/grid/register-Dwebdriver.ie.driver="D:\IEDriverServer.exe" -port 6666 -maxSession 5 -browser browserName="internet explorer",maxInstances=5
運行三個瀏覽器:
java -jar selenium-server-standalone-3.141.59.jar -role webdriver -hub http://172.29.10.127:4444/grid/register-Dwebdriver.chrome.driver="e:\chromedriver.exe"-Dwebdriver.ie.driver="e:\IEDriverServer.exe"-Dwebdriver.firefox.driver="e:\geckodriver.exe" -port 6666 -maxSession 5 -browser browserName="internet explorer",maxInstances=5 -browser browserName="chrome",maxInstances=5 -browser browserName="firefox",maxInstance=5web
參數說明:
>role : 參數值wevdriver表示Node節點名字
>hub : 參數值表示管理中心的Url地址,Node會鏈接到這個地址進行節點註冊
>port : 參數值表示Node節點服務的端口號爲6666,建議使用大於5000的端口號chrome
6)再次訪問http://localhost:4444/grid/console,驗證Node節點是否已在Hub上註冊成功
7)分佈式執行的測試腳本
測試邏輯:
使用FireFox瀏覽器訪問sogou首頁,進行關鍵詞「webdriver 實戰寶典」的搜索,並驗證搜索結果頁面源碼中是否出現做者名稱
測試腳本:windows
#encoding=utf-8 from selenium import webdriver from selenium.webdriver.common.keys import Keys import time driver = webdriver.Remote( #設定Node節點的Url地址,後續將經過這個地址鏈接到Node計算機 command_executor = "http://localhost:6666/wd/hub", desired_capabilities = { #指定遠程計算機執行使用的瀏覽器 "browserName":"internet explorer", "video":"True", #遠程計算機的平臺 "platform":"WINDOWS" #"platform":"windows_nt" } ) print ("Video" + "http://www.baidu.com" + driver.session_id) try: driver.implicitly_wait(30) driver.maximize_window() driver.get("http://www.sogou.com") assert u"搜索" in driver.title ele = driver.find_element_by_id("query") ele.send_keys(u"webdriver 實戰寶典") ele.send_keys(Keys.RETURN) time.sleep(3) assert u"吳曉華" in driver.page_source print "done!" finally: driver.quit()
測試結果:在機器B上能夠看到,計算機會自動啓動瀏覽器執行測試腳本,執行完畢後瀏覽器會自動退出。在機器A上能夠看到自動化測試的執行結果瀏覽器
四、實現併發的分佈式自動化測試
Selenium Grid不只支持在同一臺機器上同時啓動好幾個瀏覽器併發跑測試用例,也支持同時在多臺不一樣機器上啓動不一樣的瀏覽器併發跑測試用例。
操做步驟:
(1)在機器A、B和C的D盤根目錄(Webdriver驅動所在目錄)放入selenium-server-standalone-3.141.59.jar
(2)機器A啓動Hub服務
(3)機器A從新打開一個CMD,並註冊爲節點
(4)機器B、機器C打開Cmd,並註冊爲節點
注意:註冊的A、B和C機器節點的端口號必須不一致
測試腳本:session
#encoding=utf-8 from multiprocessing import Pool import os, time from selenium import webdriver from selenium.webdriver.common.keys import Keys from multiprocessing import Manager, current_process def node_task(name, lock, arg, successTestCases, failTestCases): # 獲取當前進程名 procName = current_process().name print procName time.sleep(1.2) print arg['node'] print arg["browerName"] print 'Run task %s (%s)...\n' % (name, os.getpid()) start = time.time() driver = webdriver.Remote( command_executor = "%s" %arg['node'], desired_capabilities={ "browserName": "%s" %arg["browerName"], "video": "True", "platform": "WINDOWS"}) try: driver.implicitly_wait(30) driver.maximize_window() driver.get("http://www.sogou.com") assert u"搜狗" in driver.title elem = driver.find_element_by_id("query") elem.send_keys(u"webdriver實戰寶典") time.sleep(2) elem.send_keys(Keys.RETURN) assert u"吳曉華" not in driver.page_source # 請求獲取共享資源的鎖 lock.acquire() # 向進程間共享列表successTestCases中添加執行成功的用例名稱 successTestCases.append("TestCase" + str(name)) # 釋放共享資源的鎖,以便其餘進程能獲取到此鎖 lock.release() print "TestCase" + str(name) + " done!" except AssertionError,e: print "AssertionError occur!""testCase" + str(name) print e # 截取屏幕 driver.save_screenshot('e:\\screenshoterror' + str(name) + '.png') lock.acquire() # 向共享列表failTestCases中添加執行失敗的用例名稱 failTestCases.append("TestCase" + str(name)) lock.release() print u"測試用例執行失敗" except Exception,e: print "Exception occur!" print e driver.save_screenshot('e:\\screenshoterror' + str(name) + '.png') # 請求得到共享資源操做的鎖,操做完後自動釋放 with lock: # 向共享列表failTestCases中添加執行失敗的用例名稱 failTestCases.append("TestCase" + str(name)) print u"測試用例執行失敗" finally: driver.quit() end = time.time() print 'Task %s runs %0.2f seconds.' % (name, (end - start)) def run(nodeSeq): # 建立一個多進程的Manager實例 manager = Manager() # 定義一個共享資源列表successTestCases successTestCases = manager.list([]) # 定義一個共享資源列表failTestCases failTestCases = manager.list([]) # 建立一個資源鎖 lock = manager.Lock() # 打印主進程的進程ID print 'Parent process %s.' % os.getpid() # 建立一個容量爲3的進程池 p = Pool(processes=3) testCaseNumber = len(nodeSeq) for i in range(testCaseNumber): # 循環建立子進程,並將須要的數據傳入子進程 p.apply_async(node_task, args=(i + 1, lock, nodeSeq[i], successTestCases, failTestCases)) print 'Waiting for all subprocesses done...' # 關閉進程池,再也不接受新的請求任務 p.close() # 阻塞主進程直到子進程退出 p.join() return successTestCases, failTestCases def resultReport(testCaseNumber, successTestCases, failTestCases): # 下面代碼用於打印本次測試報告 print u"測試報告:\n" print u"共執行測試用例:" + str(testCaseNumber) + u"個\n" print u"成功的測試用例:", str(len(successTestCases)) if len(successTestCases) > 0: for t in successTestCases: print t else: print u"無" print u"失敗的測試用例:", str(len(failTestCases)) if len(failTestCases) > 0: for t in failTestCases: print t else: print u"無" if __name__ == '__main__': # 節點列表 nodeList=[ {"node":"http://127.0.0.1:6666/wd/hub","browerName":"internet explorer"}, {"node":"http://127.0.0.1:6666/wd/hub","browerName":"chrome"}, {"node":"http://127.0.0.1:6666/wd/hub", "browerName":"firefox"}] # 獲取節點個數 testCaseNumber = len(nodeList) # 開始多進程分佈式測試 successTestCases, failTestCases = run(nodeList) print 'All subprocesses done.' # 在控制檯中打印測試報告 resultReport(testCaseNumber, successTestCases, failTestCases)
五、注意點:
jar和Webdriver瀏覽器驅動放在同一目錄下
機器A:啓動Hub
機器B:註冊到這個Hub
程序:在機器A運行,而後指定機器B的ip做爲driver的參數,而後能夠在機器B運行測試程序併發