Selenium Grid2
利用Grid可以在不同的主机上建立主节点(hub)和分支节点(node)。使主节点上的测试用例在不同的分支节点上运行,可以搭建不同的环境,从而使一份测试用例完成在不同环境下的验证。Selenium Grid2已经集成到selenium server中了(selenium-server-stanalon-xxx.jar包中)。
9.1 Selenium2工作原理
Selenium2 中因为使用的WebDriver,这个技术不是靠js 驱动的,而是直接调用浏览器的原生态接口驱动的。所以就没有同源问题,也就不需要使用RC 来执行本地脚本了(当然缺点就是并不是所有的浏览器都有提供很好的驱动支持,但JavaScript却是所有浏览器都通用的)。所以Selenium2 中执行本地脚本的方式是:通过本地WebDriver 驱动直接调用本地浏览器接口就可以了。
9.2Selenium Server环境配置
第一步,配置java环境:java 下载地址:http://www.java.com/zh_CN/download/manual.jsp双击下载的JDK ,设置安装路径。这里我们选择默认安装在C:\Java\jdk1.7.0_45\
目录下。下面设置环境变量:“我的电脑”右键菜单--->属性--->高级--->环境变量--->系统变量-新建..
变量名:JAVA_HOME
变量值:C:\Java\jdk1.7.0_45\
变量名:CALSS_PATH
变量值:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
找到path 变量名—>“编辑”添加:
变量名:PATH
变量值:%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
在Windows 命令提示符下验证java 是否成功:java –version
第二步,下载运行selenium server:下载地址:http://www.seleniumhq.org/download/在页面的左侧列表中找到selenium-server-standalone-XXX.jar 进行下载。下载完成可以放到任意位置,直接在命令提示符下启动Selenium Server:
C:\selenium> java -jarselenium-server-standalone-XXX.jar
执行se_rc.py 脚本,Selenium Server 将会做为代理,执行客户端与服务器端的请求与返回信息。
Se_rc.py
<pre name="code" class="html">#coding=utf-8
from selenium import selenium
import unittest, time, re
classserc(unittest.TestCase):
def setUp(self):
self.verificationErrors = []
self.selenium = selenium("localhost", 4444,"*chrome","http://www.baidu.com/")
self.selenium.start()
def test_serc(self):
sel = self.selenium
sel.open("/")
sel.type("id=kw","selenium grid")
sel.click("id=su")
sel.wait_for_page_to_load("30000")
def tearDown(self):
self.selenium.stop()
self.assertEqual([],self.verificationErrors)
if __name__ == "__main__":
unittest.main()
9.3 SeleniumGrid工作原理
Selenium Grid是进行分布式测试的工具,其整体结构是一个hub节点和若干个node代理节点组成。Hub用来管理各个代理节点的注册和撞他信息,并且接受远程客服端代码的请求调用,然后把请求的命令再转发给各个代理节点来执行。使用selenium grid远程执行测试的代码与直接调用Selenium-Server是一样的(只是环境启动的方式不一样,需要启动一个hub和至少一个node):
> java -jarselenium-server-standalone-x.xx.x.jar -role hub
> java -jarselenium-server-standalone-x.xx.x.jar -role node
上面是启动一个hub 和一个node,hub 默认端口号为4444,node 默认端口号为5555;若是同一台机器要启动多个node 则要注意端口分配问题,可以这样来启动多个node:
> java -jar selenium-server-standalone-x.xx.x.jar-role node -port 5555
> java -jarselenium-server-standalone-x.xx.x.jar -role node -port 5556
> java -jarselenium-server-standalone-x.xx.x.jar -role node -port 5557
调用Selenium Grid 的基本结构图如下:
上面是使用Selenium Grid 的一种普通方式,仅仅使用了其支持的分布式执行的功能,即当你同时需要测试用例比较多时,可以平行的执行这些用例进而缩短测试总耗时;关于并发的技术需要借助编程语言的多线程技术,我们会后面的章节深入学习Python 的多线程技术。除此之外,Selenium Grid 还支持一种更友好的功能,即可以根据你用例中启动测试的类型来相应的把用例转发给符合匹配要求的测试代理。例如你的用例中指定了要在Liunux 上FireFox 的17 版本进行测试,那么Selenium Grid 会自动匹配注册信息为Linux、且安装了FireFox17 的代理节点,如果匹配成功则转发测试请求,如果失败则拒绝请求。使用SeleniumGrid 的远程兼容性测试的代码同上。其调用的基本结构图如下:
下面我们就来演示启动一个hub 主节点和两个node 分支节点。
通过浏览器访问gird 的控制台:http://127.0.0.1:4444/grid/console
通过控制台查看启动的节信息:
Node(5555)配置信息:
port:5555
servlets:[]
host:192.168.5.57
cleanUpCycle:5000
browserTimeout:0
hubHost:192.168.5.57
registerCycle:5000
capabilityMatcher:org.openqa.grid.internal.utils.DefaultCapabilityMatcher
newSessionWaitTimeout:-1
url:http://192.168.5.57:5555
remoteHost:http://192.168.5.57:5555
prioritizer:null
register:true
throwOnCapabilityNotPresent:true
nodePolling:5000
proxy:org.openqa.grid.selenium.proxy.DefaultRemoteProxy
maxSession:5
role:node
jettyMaxThreads:-1
hubPort:4444
timeout:300000
9.4selenium Grid应用
之前编写的脚本只能在固定的某一款浏览器上执行,因为在编写测试用例之前需要先指定好浏览器的驱动(webdriver.Firefox、webdriver.Chrome),一旦确定了浏览器驱动是不能进行更改的。我们希望写好的测试用例可以*的切换成不同的浏览器来执行。
9.4.1 认识Remote
WebDriver 提供了Remote 可以发送指令到远程服务器控制浏览器。首先我们先来认识Remote 的格式。Remote_ts.py:
</pre><pre name="code" class="html"><pre name="code" class="html"><pre name="code" class="html">from selenium.webdriver import Remote
fromselenium.webdriver.common.desired_capabilities import DesiredCapabilities
driver = Remote(command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities=DesiredCapabilities.CHROME
)
driver.get('http://www.baidu.com')
driver.find_element_by_id("kw").send_keys("selenium")
driver.find_element_by_id("su").click()
driver.quit()
command_executor 为命令执行器,它用于指定脚本执行的主机及端口。
>>> from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
>>> a=DesiredCapabilities.CHROME
>>> print a
{'platform': 'ANY', 'browserName': 'chrome', 'version': '','javascriptEnabled':
True}
Desired Capabilities 本质上是keyvalue 的对象,它告诉Selenium Server 脚本执行的基本运行环境:
'platform': 'ANY' 平台默认可以是任何(Windows,MAC,android)。
'browserName': 'chrome' 浏览器名字是chrome。
'version': '' 浏览器的版本默认为空。
'javascriptEnabled': True javascript 启动状态为True
Remote_ts.py:
from selenium.webdriver import Remote
fromselenium.webdriver.common.desired_capabilities import DesiredCapabilities
driver = Remote(command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities={'platform': 'ANY',
'browserName':'chrome',
'version': '',
'javascriptEnabled':True
}
)
driver.get('http://www.baidu.com')
driver.find_element_by_id("kw").send_keys("selenium")
driver.find_element_by_id("su").click()
driver.quit()
WebDriver API 提供了不同平台及浏览器的参数:
ANDROID ={'platform': 'ANDROID', 'browserName': 'android', 'version': '','javascriptEnabled': True}
CHROME ={'platform': 'ANY', 'browserName': 'chrome', 'version': '','javascriptEnabled': True}
FIREFOX = {'platform': 'ANY', 'browserName': 'firefox', 'version': '','javascriptEnabled': True}
HTMLUNIT ={'platform': 'ANY', 'browserName': 'htmlunit', 'version': ''}
HTMLUNITWITHJS = {'platform': 'ANY','browserName': 'htmlunit', 'version':'firefox','javascriptEnabled': True}
INTERNETEXPLORER = {'platform': 'WINDOWS','browserName': 'internet explorer', 'version': '','javascriptEnabled': True}
IPAD = {'platform': 'MAC', 'browserName': 'iPad', 'version': '','javascriptEnabled': True}
IPHONE = {'platform': 'MAC', 'browserName': 'iPhone', 'version': '','javascriptEnabled':True}
SAFARI = {'platform': 'ANY', 'browserName': 'safari', 'version': '','javascriptEnabled':True}
PHANTOMJS = {'platform': 'ANY', 'browserName': 'phantomjs', 'version': '','javascriptEnabled': True}
OPERA = {'platform': 'ANY','browserName': 'opera', 'version': '','javascriptEnabled': True}
9.4.2参数化浏览器执行用例
通过对Desired Capabilities 的分解,浏览器的配置是由browserName 所对应的值所指定的,那么实现浏览器的参数化将变得非常简单。
在运行脚本之前我们需要先启动Selenium Server,因为只对浏览器进行参数化,所以启动一个节点即可: > java -jarselenium-server-standalone-2.39.0.jar
Browsers.py
</pre><pre name="code" class="python">#coding=utf-8
fromselenium.webdriver import Remote
fromselenium.webdriver.common.desired_capabilities import DesiredCapabilities
lists=['chrome','firefox','internetexplorer']
for browser inlists:
print browser
driver = Remote(
command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities={'platform': 'ANY',
'browserName':browser,
'version': '',
'javascriptEnabled': True
})
driver.get("http://www.baidu.com")
driver.find_element_by_id("kw").send_keys(browser)
driver.find_element_by_id("su").click()
driver.close()
创建lists 数组,罗列不同的浏览器,通过for 循环读取数组中的浏览器,传参给当browserName 做为当前要执行的浏览器来运行测试用例。
9.4.3 多节点执行用例
在Selenium Grid 原理的小节中,我们演示了如何启动多个节点,下面来启动多个节点,使同一个脚本在不同的节点上执行。
在本机打开两个命令提示符窗口分别启动一个hub:
C:\selenium>java -jarselenium-server-standalone-2.39.0.jar -role hub
启动两个node(节点):
C:\selenium>java-jar selenium-server-standalone-2.39.0.jar -role node -port 5555
C:\selenium>java-jar selenium-server-standalone-2.39.0.jar -role node -port 5556
下面修改脚本使其在不同的节点与浏览器上运行:host.py:
#coding=utf-8
fromselenium.webdriver import Remote
fromselenium.webdriver.common.desired_capabilities import DesiredCapabilities
lists={ 'http://127.0.0.1:4444/wd/hub':'chrome',
'http://127.0.0.1:5555/wd/hub':'firefox',
'http://127.0.0.1:5556/wd/hub':'internetexplorer'
}
for host,browserin lists.items():
print host,browser
driver = Remote(
command_executor=host,
desired_capabilities={'platform':'ANY',
'browserName':browser,
'version': '',
'javascriptEnabled':True
}
)
driver.get("http://www.baidu.com")
driver.find_element_by_id("kw").send_keys(browser)
driver.find_element_by_id("su").click()
driver.close()
创建lists 字典,定义不同的主机端口号与浏览器,通过for 循环读取字典中的主机与浏览器给Remote,使脚本执行时调用不同的主机和浏览器。
启动远程node
我们目前启动的hub 与node 都是在一台主机上。那么要在其它主机启动node 必须满足以下几个要求:
l 本地hub 主机与远程node 主机之间可以相互ping 通。
l 远程主机必须安装运行脚本的运行环境(Python 、Selenium、浏览器及浏览器驱动)。
l 远程主机必须安装java 环境,因为需要运行SeleniumServer。
操作步骤如下:
启动本地hub 主机(本地主机IP 为:172.16.10.66):
C:\selenium>java-jar selenium-server-standalone-2.39.0.jar -role hub
启动远程主机(操作系统:Ubuntu ,IP 地址:172.16.10.34):
远程主机启动node 方式如下:
$ java -jar selenium-server-standalone-2.39.0ar-role node -port 5555 -hubhttp://172.16.10.66:4444/grid/register
(设置的端口号为:5555 ,指向的hub ip 为172.16.10.66)
修改远程主机的IP 地址及端口号,在其上面的firefox 浏览下运行脚本。host.py:
#coding=utf-8
fromselenium.webdriver import Remote
fromselenium.webdriver.common.desired_capabilities import DesiredCapabilities
lists={'http://127.0.0.1:4444/wd/hub':'chrome',
'http://172.16.10.34:5555/wd/hub':'firefox',
'http://127.0.0.1:5556/wd/hub':'internetexplorer'
}
for host,browserin lists.items():
print host,browser
driver = Remote(
command_executor=host,
desired_capabilities={'platform':'ANY',
'browserName':browser,
<span style="white-space:pre"> </span>'version': '',
<span style="white-space:pre"> </span>'javascriptEnabled':True
}
)
driver.get("http://www.baidu.com")
driver.find_element_by_id("kw").send_keys(browser)
driver.find_element_by_id("su").click()
driver.close()
现在再来运行脚本,你将会在172.16.10.34 主机上看到脚本被执行。
小技巧:
自从使用Selenium Server 执行自动化脚本后,常常会因为忘记启动Selenium Server 导致脚本运行报错。其实我们以在脚本中执行cmd 命令。如在我们创建的all_test.py 文件中添加:
import os
os.chdir('E:\\selenium')
os.system('java-jar selenium-server-standalone-2.39.0.jar')
这样就再也不会因为忘记启动Selenium Server 导致测试脚本运行失败了。
9.5 WebDriver驱动
WebDriver 所支持的驱动: