如果你會docker 那么我更推薦你看看:
http://www.lxweimin.com/p/29c7240e9f48
Selenium Grid 是什么?
Selenium Grid 是一個可以方便的讓你腳本運行在不同的平臺以及不同的瀏覽器上的一個框架。Selenium Grid 分1和2兩個版本,其中Selenium Grid 2的發布還晚于Selenium 2.0,也就是說Selenium Grid 2 并不是和Selenium 2.0 一起發布的,但是Selenium Grid 2基本上支持Selenium 2.0的所有功能。
Selenium Grid 基本結構
如上圖,Selenium Grid 由一個Hub節點和若干個Node節點組成。 其中Hub節點主要用于管理各個Node節點的注冊及其狀態,并接收Selenium Scripts腳本,然后轉發給各個Node節點去執行,所以Hub本身節點是不執行腳本的,Hub是做腳本分發,真正執行腳本都是放于Node節點上。既然Hub 會分發腳本,那么免去了一個一個Node機器上去拷貝你腳本的麻煩啦。
何時需要 Selenium Grid
在了解了什么是 Selenium Grid 和其基本結構后,那么我們開始關心我們何時需要它呢?下面列出兩點:
1. 當你的腳本需要在不同的系統和瀏覽器運行時,也就是測試需要考慮各種瀏覽器兼容性時。
2. 當你想縮短你的測試執行時間時。
當你開始考慮上面兩個問題時,那么可以考慮使用Selenium Grid .
怎么使用
注意:Selenium Grid 是用java開發的框架,所以你想運行這個框架,你需要有java環境。Java環境的搭建可以參考http://www.lxweimin.com/p/74a5ea7fd369 。
下載jar包
下載地址:http://selenium-release.storage.googleapis.com/index.html ,選取最新版本,例如寫這個文章時最新版本是2.53,那么進入2.53文件夾下載 selenium-server-standalone-2.53.0.jar 文件便可。
啟動Hub 節點:
在控制臺(終端)輸入:java -jar selenium-server-standalone-2.53.0.jar -role hub
出現類似如下圖信息便表示Hub啟動成功:
這時你可以瀏覽器打開 http://localhost:4444/grid/console ,可以看到Hub管理頁面。
點擊 view config,可以查看到當前hub節點的一些配置默認配置信息,例如:
port : 4444 這個是hub 默認的端口號;
**throwOnCapabilityNotPresent : true ** 默認為 true,表示當前hub只有在有node存在時,才會接受測試請求。為false 則反之;
capabilityMatcher : org.openqa.grid.internal.utils.DefaultCapabilityMatcher 這是一個實現了CapabilityMatcher接口的類,默認指向org.openqa.grid.internal.utils.DefaultCapabilityMatcher該類用于實現grid在分布測試任務到對應node時所使用的匹配規則,如果想要更精確的測試分配規則,那么就注冊一個自己定義的匹配類;
**prioritizer : null ** 這是一個實現了Prioritizer接口的類。設置grid執行test任務的優先邏輯;默認為null,那個腳本先到那個先執行;
newSessionWaitTimeout : -1 默認-1,即沒有超時;指定一個新的測試session等待執行的間隔時間。即一個代理節點上前后2個測試中間的延時時間,單位為毫秒;
**browserTimeout : 0 ** 瀏覽器無響應的超時時間,默認為0表示沒有超時時間
修改 hub 的配置
想要修改 hub 的配置有兩種方法。
通過命令修改
例如假設我的 4444端口被別的程序占用了,我想修改默認的端口為4445,則如下:
java -jar selenium-server-standalone-2.53.0.jar -role hub -port 4445
通過Json文件修改配置:
- 新建個json格式的文件,內容如下(這里僅僅修改了maxSession的配置,默認是5),并放于跟Grid jar包同一目錄:
{ "host": null, "port": 4444, "newSessionWaitTimeout": -1, "servlets" : [], "prioritizer": null, "capabilityMatcher": "org.openqa.grid.internal.utils.DefaultCapabilityMatcher", "throwOnCapabilityNotPresent": true, "nodePolling": 5000, "cleanUpCycle": 5000, "timeout": 300000, "browserTimeout": 0, "maxSession": 10 }
- 執行命令:java -jar selenium-server-standalone-2.53.0.jar -role hub -hubConfig hub.json
這時再到 Grid Console 頁面查看,maxSession 參數已經修改成 10.
node 節點Selenium 環境要求
在添加node節點前,我們先關注下,node 節點對環境要求:
1. node 節點必須要有 java 環境
2. node 節點跟hub 節點機器間可以互相 ping 通。(不通時關閉防火墻和安全軟件再試試)
3. node 節點負責執行Selenium 腳本,所以必須有Selenium 環境(腳本語言對應的環境如java, 各個瀏覽器及其對應的driver)
添加 node 節點
如果你是跟hub同一臺機器中添加可以直接在控制臺(終端)輸入如下命令:
java -jar selenium-server-standalone-2.53.0.jar -role node
如果你想在別的機器上添加node節點則控制臺(終端)輸入如下命令:
java -jar selenium-server-standalone-2.53.0.jar -role node -hub http://192.168.1.110:4444/grid/register
添加完節點后,可以在 Grid Console 頁面上查看到已經注冊進來的node節點信息和配置。如下圖:
補充:使用 -role node 注冊表示這個node節點既可以支持Selenium Remote Control 也支持Webdriver
java -jar selenium-server-standalone-2.53.0.jar -role rc //注冊的節點僅支持Selenium Remote Control
java -jar selenium-server-standalone-2.53.0.jar -role wd //注冊的節點僅支持WebDriver
修改 node 配置
同樣node的配置有兩種方式
通過命令修改
java -jar selenium-server-standalone-2.53.0.jar -role rc -port 6666
通過json文件修改(3.X版本請參考文章末尾配置)
例如新建一個node.json文件,如下內存,并放于Grid 同級目錄下
{ "capabilities": [ { "browserName": "chrome", "maxInstances": 5, "platform": "WINDOWS", "version":"51" }, { "browserName": "firefox", "maxInstances": 6, "platform": "WINDOWS", "version":"46.0.1" }, { "browserName": "internet explorer", "maxInstances": 2, "platform": "WINDOWS", "webdriver.ie.driver": "IEDriverServer.exe" } ], "configuration": { "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy", "maxSession": 5, "port": 5555, "register": true, "registerCycle": 5000, "hub": "http://192.168.84.209:4444" } }
重要參數說明:
**"browserName": “chrome" **這個很重要,表示你注冊的瀏覽器
"maxInstances": 5 這個參數表示最多啟動該瀏覽器的個數
"webdriver.ie.driver": “IEDriverServer.exe” 每個瀏覽器driver放置的位置,建議放跟Grid 同級目錄下
執行命令:
java -jar selenium-server-standalone-2.53.0.jar -role node -nodeConfig node.json -hub http://192.168.84.209:4444/grid/register
最后查看Grid Console 頁面,顯示如下node節點信息:
到此為止,我們已經配置好Hub 和需要的多個Node 節點,下去我們需要開始編寫測試代碼
測試代碼:
在編寫代碼之前我們先簡單了解下兩個工具Maven 和 TestNG。
Maven:是一個項目管理工具,可以用于項目構建打包等,還可以用于項目依賴包管理。
TestNG: 是一個強大的測試框架,設計靈感來源于junit,但優于junit,它提供了很強大的注解,便于我們對case的各種操作。
新建 Maven 工程
我們可以通過IDEA來新建一個Maven 工程,新建過程可以參考http://www.lxweimin.com/p/6ca7bbcdf2dd , 并在pom.xml 文件添加selenium 和 TestNG的依賴包如下:
<!-- http://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.53.0</version>
</dependency>
<!-- http://mvnrepository.com/artifact/org.testng/testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.9.10</version>
</dependency>
編寫腳本
例如我想在遠程的node 節點(192.168.84.19:5555)機器上啟動Chrome/IE/firefox瀏覽器,并打開百度頁面,這里我們需要借助DesiredCapabilities類來指定采用哪個瀏覽器,用RemoteWebDriver 來實現遠程運行,具體代碼如下:
// 啟動192.168.84.209:5555 node節點的Chrome
@Test
public void testChrome() throws MalformedURLException, InterruptedException {
DesiredCapabilities chromeDC = DesiredCapabilities.chrome();
WebDriver driver = new RemoteWebDriver(new URL("http://192.168.84.209:5555/wd/hub"), chromeDC);
driver.get("http://www.baidu.com");
Thread.sleep(5000);
driver.quit();
}
// 啟動192.168.84.19:5555 node節點的firefox
@Test
public void testFF() throws MalformedURLException, InterruptedException {
DesiredCapabilities firefoxDC = DesiredCapabilities.firefox();
WebDriver driver = new RemoteWebDriver(new URL("http://192.168.84.19:5555/wd/hub"), firefoxDC);
driver.get("http://www.baidu.com");
Thread.sleep(5000);
driver.quit();
}
// 啟動192.168.84.19:5555 node節點的IE
@Test
public void testIE() throws MalformedURLException, InterruptedException {
DesiredCapabilities ieDC = DesiredCapabilities.internetExplorer();
WebDriver driver = new RemoteWebDriver(new URL("http://192.168.84.19:5555/wd/hub"), ieDC);
driver.get("http://www.baidu.com");
Thread.sleep(5000);
driver.quit();
}
補充 DesiredCapabilities類,除了可以指定瀏覽器的名稱還可以指定平臺和瀏覽器版本以及瀏覽器支持的其他功能
從上面的腳本我們已經大概知道如果去指定某個腳本在某個系統和瀏覽器中運行,但是平時我們的case基本上希望的是所有的case可以在期望的平臺和瀏覽器中快速運行,這里其實有兩個需求,一個是所有的腳本能都在指定瀏覽器中運行 另一個就是盡可能快速運行。
先來解決第一個需求:假設現在我有個測試腳本實現了 ”打開百度界面,并輸入頁面title“,我希望他可以在A機器(192.168.84.209)上的chrome 瀏覽器 和 firefox瀏覽器運行,在B(192.168.84.19)機器上的IE瀏覽器運行。那么我們代碼可以如下設計思路:
1. 通過TestNG 提供的@DataProvider 實現數據驅動(也可以通過.xml做數據來源去實現)
2. 通過不同參數,把腳本分配到不同的node上的運行
具體實現代碼如下:
// 通過TestNG 提供的注解,實現數據驅動
@DataProvider(name = "data")
public Object[][] data() {
return new Object[][]{{"http://192.168.84.209:5555", "chrome"},
{"http://192.168.84.209:5555", “firefox"},
{"http://192.168.84.19:5555", "ie"}};
}
/**
* @param nodeURL node 節點的地址
* @param browser node 節點的瀏覽器
* @throws MalformedURLException
*/
@Test(dataProvider = "data") // 獲取對應的數據源
public void openBaiduPageTest(String nodeURL, String browser) throws MalformedURLException {
DesiredCapabilities desiredCapabilities;
// 判斷要打開的瀏覽器
if (browser .equals("chrome")) {
desiredCapabilities = DesiredCapabilities.chrome();
} else if (browser .equals( "ie")) {
desiredCapabilities = DesiredCapabilities.internetExplorer();
} else {
desiredCapabilities = DesiredCapabilities.firefox();
}
// 拼接處要執行腳本的node 節點地址
String url = nodeURL + "/wd/hub";
WebDriver driver = new RemoteWebDriver(new URL(url), desiredCapabilities);
// 打開百度
driver.get("http://www.baidu.com");
System.out.println(browser + driver.getTitle());
// 關閉瀏覽器
driver.quit();
}
需求1解決了,我們再來考慮下需求2:如何盡可能快速運行,畢竟現在大多研發團隊都是走敏捷,如果等你腳本執行幾小時或者更長時間,那簡直要命。解決思路可以通過并行執行case腳本來解決。TestNG不僅僅能提供數據驅動的方式,也提供了多種并發方式,這樣就很好解決了我們case并行執行的要求,具體解決如下:
在項目中新建個.xml 文件,如下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Default Suite" parallel="methods" thread-count=“3">
<test name="Selenium_Grid_Demo">
<classes>
<class name="com.grid.demo.GridDemo"/>
</classes>
</test> <!-- Selenium_Grid_Demo -->
</suite> <!-- Default Suite -->
其中 <suite name="Default Suite" parallel="methods" thread-count="1”> 中的 thread-count 參數值就是并發的進程數,parallel 的參數表示通過哪種方式進行并發可以是 methods , classes , test 。 xml里面更多的配置有興趣的可以百度了解。
例如我的測試GridDemo 類里面有3個case了,我也新建了如上的.xml文件,那么我運行該xml文件會看到這三個case同時執行
通過Jenkins 執行腳本
Jenkins 是個CI(持續集成)工具,功能非常強大,插件也非常多,下面簡單介紹如何把已經編寫好的腳本放到Jenkins執行。
1. 搭建Jenkins 環境 (百度很多,不詳細說明)
2. 修改本地Maven 項目的pom.xml 文件,添加如下插件:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<suiteXmlFiles>
<!--要執行的testng的.xml文件路徑-->
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
1. 打開Jenkins平臺,新建一個Maven,便可以
Selenium Grid 的GUI管理工具
最后推薦兩個Grid的GUI 管理工具:
1. Jenkins 的Selenium Plugin 插件,可以在Jenkins插件中找到
安裝完成后會在導航中添加Grid的入口。
2. VisGrid
下載地址:http://www.codoid.com/products/view/2/30
補充 (17.07.27更新)
最近因為接手一個項目,又需要重新搭建Grid ,而此時的Webdriver已經是3.x版本了,同時我們看到的Grid的selenium-server-standalone jar包也升級到了3.X 版本,雖然基本用法保持一樣,但是在配置Node的json文件時,有點小變動,所以如果你是用3.X版本的Grid那么請參考: https://github.com/SeleniumHQ/selenium/blob/master/java/server/src/org/openqa/grid/common/defaults/DefaultNodeWebDriver.json 中的配置,同時想看Grid的官方幫助請參考: https://github.com/SeleniumHQ/selenium/wiki/Grid2 。
最后我隨手貼出官方給出的默認Node Json配置文件:
{
"capabilities":
[
{
"browserName": "firefox",
"maxInstances": 5,
"seleniumProtocol": "WebDriver"
},
{
"browserName": "chrome",
"maxInstances": 5,
"seleniumProtocol": "WebDriver"
},
{
"browserName": "internet explorer",
"maxInstances": 1,
"seleniumProtocol": "WebDriver"
}
],
"proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
"maxSession": 5,
"port": 5555,
"register": true,
"registerCycle": 5000,
"hub": "http://localhost:4444",
"nodeStatusCheckTimeout": 5000,
"nodePolling": 5000,
"role": "node",
"unregisterIfStillDownAfter": 60000,
"downPollingLimit": 2,
"debug": false,
"servlets" : [],
"withoutServlets": [],
"custom": {}
}
(2018.07.03更新)補充2:
最近偶然查看Selnium 發布的修改log中看到,在Selenium v3.7.0 版本后DesiredCapabilities被遷移到MutableCapabilities或最好使用ImmutableCapabilities 。
https://github.com/SeleniumHQ/selenium/blob/master/java/CHANGELOG
* Migrated from using `DesiredCapabilities` to either
`MutableCapabilities` or (preferably) `ImmutableCapabilities`.