selenium Grid详解
什么是selenium Grid
① Selenium Grid 是Selenium套件的一部分,它专门用于并行运行多个测试用例在不同的浏览器、操作系统和机器上。
② Selenium Grid 主要使用 master-slaves 或者 hub-nodes 理念 :一个 master/hub 和多个基于 master/hub 注册的子节点 slaves/nodes 。
当我们在master上基于不同的浏览器/系统运行测试用例时,master将会将测试用例分发给适当的node运行。(当然也可以作为兼容性测试工具将测试用例运行在不同的web浏览器上)
③
④ selenium Grid 主要的作用:实现分布式执行测试,解决浏览器兼容性问题。【通过 Selenium Grid 的可以控制多台机器多个浏览器执行测试用例,分布式上执行的环境在 Selenium Grid 中称为node节点。】
⑤举例:
当自动化测试用例达到一定数量的时候,比如上万,一台机器执行全部测试用例耗时5个小时(只是举例,真正的耗时是需要根据测试用例场景的复杂度决定的),而如果需要覆盖主流浏览器比如Chrome、Firefox,加起来就是10个小时;这时候领导跟你说有什么办法可以解决这个执行速度?当然最笨的办法就是另外拿台机器,然后部署环境,把测试用例分开去执行然后合并结果即可。而Selenium也想到了这点,所以有了Selenium Grid的出现,它就是解决分布式执行测试的痛点。
⑥总结:
- Slenium Grid 分布式测试由hub主节点和node节点组成
- Hub节点用来管理node节点注册信息。
- 脚本——》Hub节点——》node节点——》浏览器
什么时候用Selenium Grid
①同时在不同的浏览器、操作系统和机器上运行测试。最大程度用于兼容性测试。
②减少测试用例的运行时间。
Selenium Grid工作原理
① Selenium Grid 实际它是基于Selenium RC的,而所谓的分布式结构就是由一个hub节点和若干个node代理节点组成。
②Hub节点用来管理各个代理节点的注册信息和状态信息,并且接受远程客户端代码的请求调用,然后把请求的命令转发给代理节点来执行。
如何启动Selenium Grid
启动 Selenium Grid 有三种方式:一种直接用命令行方式;另一种用JSON
配置文件;最后一种docker
启动。
首先需要下载:selenium-server-standalone-3.9.1.jar【可以理解为搭建selenium Grid环境】
下载地址:http://selenium-release.storage.googleapis.com/index.html
1、命令行方式启动 selenium Grid
①进入selenium-server-standalone-3.9.1.jar文件所在的目录位置。
②进入cmd命令行终端中。
③启动Hub,命令如下:
java -jar selenium-server-standalone-3.9.1.jar -role hub -maxSession 10 -port 4444
运行结果如下图:
命令参数解析:
- - role :此参数后跟hub或者node;表示此机器启动hub节点或者node子节点;
- - port :此参数后跟端口号;设置启动hub或者node节点服务的端口号;hub的默认端口是4444;这里使用的是默认的端口,当然可以自己配置;
- - maxSession :此参数后跟最大会话请求数;最大会话请求,这个参数主要用于并发执行测试用例,默认是1,建议设置10及以上。
④浏览器打开地址:http://localhost:4444/grid/console,出现如下图表示hub节点启动成功。
⑤启动node节点【启动hub节点后最少需要一个node节点,不然启动hub节点就没有意义】
而node节点同样可以与hub节点在同一台机器上运行,如下例就是hub节点与node节点同机的例子。
hub机 |
ip:10.200.145.226 |
node1机 |
ip:10.200.145.226 |
命令行:
java -jar selenium-server-standalone-3.9.1.jar -role node -port 6666 -hub http://10.200.145.226:4444/grid/register/ -maxSession 5 -browser browserName=chrome,seleniumProtocol=WebDriver,maxInstances=5,platform=WINDOWS,version=96.0
运行结果如下图:
命令参数解析:
- -role node :表示启动的是node节点
- -port 5555 :指定node节点端口
- - browser :启动的node节点服务设置浏览器参数信息
- browsderName=chrome :浏览器的名称
- seleniumProtocol=WebDriver :selenium工具的实现协议
- maxInstances=5 :最大实例(该node节点上最多可运行的浏览器数),该值不能大于前面开启hub节点服务时 maxSession 参数的值
- platform=WINDOWS :表示操作系统。
- version=96.0 :表示浏览器版本。
- Dwebdriver.chrome.driver=chromedriver.exe :浏览器驱动,如果是其他浏览器就写对应的浏览器驱动的名字;如火狐浏览器: Dwebdriver.firefox.driver=geckodriver.exe
- - hub :此参数后面跟开启hub节点时生成的Nodes节点应该连接的地址,表示需要连接的hub机地址
⑥浏览器重新打开地址:http://localhost:4444/grid/console,如出现下图则表示node节点服务启动成功:
【注意】如果使用的chromedriver.exe与selenium-server-standalone-3.9.1.jar版本或者浏览器chrome版本不匹配都会报错提示,具体原因需要具体解决。
2、Json配置文件启动 selenium Grid
①创建hub的Json配置文件。
代码如下:将下述代码保存为 hub_config.json 文件,放在hub节点机器的与selenium server(即selenium-server-standalone-3.9.1.jar)相同的路径下。
{ "port": 4444, "newSessionWaitTimeout": -1, "servlets" : [], "withoutServlets": [], "custom": {}, "capabilityMatcher": "org.openqa.grid.internal.utils.DefaultCapabilityMatcher", "registry": "org.openqa.grid.internal.DefaultGridRegistry", "throwOnCapabilityNotPresent": true, "cleanUpCycle": 5000, "role": "hub", "debug": false, "browserTimeout": 0, "timeout": 1800 }
②创建nodes的Json配置文件。
代码如下:保存为 node_config.json 文件(注意将hub对应的值改为node节点机器的IP地主),放在node节点上和selenium server相同的路径下。(当多个node时需将该文件放在多个node机器上或者同一个机器上启动多个node)
{ "capabilities": [ { "browserName": "firefox", "marionette": true, "maxInstances": 5, "seleniumProtocol": "WebDriver" }, { "browserName": "chrome", "maxInstances": 5, "seleniumProtocol": "WebDriver" }, { "browserName": "internet explorer", "platform": "WINDOWS", "maxInstances": 1, "seleniumProtocol": "WebDriver" }, { "browserName": "safari", "technologyPreview": false, "platform": "MAC", "maxInstances": 1, "seleniumProtocol": "WebDriver" } ], "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy", "maxSession": 5, "port": -1, "register": true, "registerCycle": 5000, "hub": "http://192.168.1.100:4444", "nodeStatusCheckTimeout": 5000, "nodePolling": 5000, "role": "node", "unregisterIfStillDownAfter": 60000, "downPollingLimit": 2, "debug": false, "servlets" : [], "withoutServlets": [], "custom": {} }
③
hub机器上命令行运行: java -jar selenium-server-standalone-3.141.59.jar -role hub -hubConfig hub_config.json
node机器上命令行运行: java -jar selenium-server-standalone-3.141.59.jar -role node -nodeConfig node_config.json
【注意】命令行方式启动 selenium Grid、Json配置文件启动 selenium Grid 两种方式的缺点:不易启动和维护
- 每个node需要下载和配置依赖
- java 进程占内存
- 出现问题时需手动启动
- 不易维护
- 扩展性差
3、docker启动 selenium Grid
docker简介
- https://docs.docker.com/docker-hub/
- https://yeasy.gitbooks.io/docker_practice/appendix/repo/mysql.html
- https://docker-curriculum.com/
- https://towardsdatascience.com/learn-enough-docker-to-be-useful-1c40ea269fa8
docker启动 Selenium Grid
docker上已经有selenium官方的Selenium Grid镜像,只有你已经安装了docker,即可使用。
- 启动hub:docker run -d -p 4444:4444 --name selenium-hub selenium/hub
- 启动node(Chrome&&Firefox):
- docker run -d --link selenium-hub:hub selenium/node-chrome
- docker run -d --link selenium-hub:hub selenium/node-firefox
运行命令将会下载内置镜像文件(包括java、Chrome、Firefox、selenium-server-standalone-XXX.jar 等运行selenium所需的环境);此时你可以访问:http://localhost:4444/grid/console
如果需要多个Chrome node则继续运行这个命令: docker run -d --link selenium-hub:hub selenium/node-chrome ,刷新则看到多了一个Chrome实例。
通过运行命令: docker ps ,显示正在运行的容器:
docker 组件启动 Selenium Grid
①selenium Grid
通常需要启动一个hub,多个nodes像Chrome、Firefox等。我们可以把他们定义到一个文件中叫做 docker-compose.yml ,通过一个命令来整体启动,docker提供了一个这样的工具 –Docker-Compose
。
②安装docker-compose
,一旦安装成功,则创建一个新的文件夹,创建文件 docker-compose.yml , docker-compose.yml 内容:
version: "3" services: selenium-hub: image: selenium/hub container_name: selenium-hub ports: - "4444:4444" chrome: image: selenium/node-chrome depends_on: - selenium-hub environment: - HUB_PORT_4444_TCP_ADDR=selenium-hub - HUB_PORT_4444_TCP_PORT=4444 firefox: image: selenium/node-firefox depends_on: - selenium-hub environment: - HUB_PORT_4444_TCP_ADDR=selenium-hub - HUB_PORT_4444_TCP_PORT=4444
docker-compose命令:
- 运行命令启动(到
docker-compose.yml
路径下):docker-compose up -d
- 查看启动是否成功:
docker-compose ps
- 创建更多实例:
docker-compose scale chrome=5
- 关闭命令:
docker-compose down
浏览器打开http://localhost:4444/grid/console将会看到:
运行脚本的话直接运行就好(IP:http://localhost:4444/wd/hub) ,和上边两种的方法不太一样;不会有浏览器打开(容器内部运行),但是已经运行成功:
import unittest from selenium import webdriver class MyTestCase(unittest.TestCase): def setUp(self): ds = {'platform': 'ANY', 'browserName': "chrome", 'version': '', 'javascriptEnabled': True } self.dr = webdriver.Remote('http://localhost:4444/wd/hub', desired_capabilities=ds) def test_something(self): self.dr.get("https://www.baidu.com") self.assertEqual(self.dr.name, "chrome") def test_search_button(self): self.dr.get("https://www.baidu.com") self.assertTrue(self.dr.find_element_by_id("su").is_displayed()) def tearDown(self): self.dr.quit() if __name__ == '__main__': unittest.main()
Selenium Grid 脚本执行(在node节点机器上执行)
单node节点单浏览器执行代码脚本:
import time from selenium import webdriver from selenium.webdriver.common.by import By cap = dict(browserName="chrome", version="96.0", platform="WINDOWS") # 初始化连接 driver = webdriver.Remote('http://10.200.145.226:4444/wd/hub', desired_capabilities=cap) driver.get("https://www.baidu.com/") driver.find_element(By.ID, "kw").send_keys("selenium grid") print(driver.title) time.sleep(2) driver.quit()
单node节点多浏览器并行执行代码脚本:
import threading import time from selenium import webdriver from selenium.webdriver.common.by import By def task(driver): driver.get("https://www.baidu.com/") driver.find_element(By.ID, "kw").send_keys("selenium grid") time.sleep(2) driver.quit() def getDrivder(browser): # 浏览器描述 cap = None # 判断浏览器种类 if browser == "chrome": cap = webdriver.DesiredCapabilities.CHROME.copy() # 该类封装了各个浏览器的运行参数 elif browser == "firefox": cap = webdriver.DesiredCapabilities.FIREFOX.copy() # 重构浏览器描述 cap["platform"] = "WINDOWS" # 返回驱动对象 return webdriver.Remote('http://10.200.145.226:6666/wd/hub', desired_capabilities=cap) if __name__ == '__main__': browsers = ("chrome", "firefox") for b in browsers: # 获取驱动 driver = getDrivder(b) # 创建线程执行任务 threading.Thread(target=task, args=(driver,)).start()