前记:python+flask+bootstrap+macaca 搭建 web/ android 自动化测试管理平台
使用 python + flask 搭建的 selenium web 自动化测试平台已经运行一段时间。 一直以来都是需要在自己的windows 机上启动 selenium server 作为运行的媒介,不是很方便。于是考虑使用docker 来作为运行用例的平台。
安装步骤:
1. 安装docker。
首先打算在测试的linux 服务器上搭建,无奈服务器linux版本太低(上面的部署的服务还挺多的,不想冒升级内核版本的风险),尝试了很多次都无法愉快地把docker 跑起来,最终选择先在windows 服务器下先尝试搭起来。 具体安装步骤网上很多,这里就不多说了。
2. 拉取所需的docker镜像。
目前使用到两个镜像:
docker pull selenium/hub
docker pull selenium/node-chrome
3. 启动对应docker镜像。
按selenium docker 官方github上的推荐方式启动如下:
docker network create grid
docker run -d -p 4444:4444 --net grid --name selenium-hub selenium/hub
docker run -d --net grid -e hub_host=selenium-hub -v /dev/shm:/dev/shm selenium/node-chrome
服务顺利起来了,可以查看到对应selenium节点:
http://192.168.99.100:4444/grid/console#
4. 跑一下测试脚本,可以正常调用服务进行测试:
from selenium import webdriver
chrome_options = webdriver.chromeoptions()
driver = webdriver.remote(command_executor='http://192.168.99.100:4444/wd/hub',
desired_capabilities = chrome_options.to_capabilities())
driver.get('http://www.baidu.com/')
driver.find_element_by_id("kw").send_keys("docker selenium test")
driver.find_element_by_id("su").click()
driver.get_screenshot_as_file("c://img1.png")
driver.quit()
踩坑记
1. 外网访问docker 里的selenium 服务。
设计的架构里,测试平台将调用对应的 selenium server 服务发起测试。但现在docker只能在windows 服务器内访问,因此需要把对应的端口转发出去。
步骤:
1.1 把selenium docker镜像对应的 ip 192.168.99.100,端口为4444 的docker服务转发到本地(对应的局域网ip 为 172.16.100.1):
cmd 执行:
netsh interface portproxy add v4tov4 listenport=4444 listenaddress=172.16.100.1 connectport=4444 connectaddress=192.168.99.100
1.2 windows 防火墙中添加端口4444 的对应转发规则(防火墙》高级设置 ,分别添加入站规则和出站规则)
这样,局域网的服务器就可以通过 172.16.100.1:4444 调用selenium hub 的服务了。
2. 窗口最大化失败
在脚本中对浏览器进行最大化操作:
driver.maximize_window()
这个命令一向运行是没问题的,但是在docker 中却报错如下:
message: unknown error: failed to change window state to maximized, current state is normal
查了一下,说是selenium 的bug。 找了一下,没有合适的解决方案,粗暴解决如下:
try:
driver.maximize_window()
except webdriverexception as e:
log.log().logger.info(e)
driver.set_window_size(1920, 1080) #如果最大化失败,设置窗口大小为 1920*1080
3. chrome option 不生效。
因为部分用例需要模拟移动设备,或设置浏览器为英文,所以使用 chrome option进行设置。 原来的初始化脚本如下:
desired_caps_web = webdriver.desiredcapabilities.chrome
devicelist = ['galaxy s5', 'nexus 5x', 'nexus 6p', 'iphone 6', 'iphone 6 plus', 'ipad', 'ipad pro']
if devicename!='' :
if devicename not in devicelist:
devicename = devicelist[2]
chrome_option = {
'args': ['lang=en_us','start-maximized'],
'extensions': [], 'mobileemulation': {'devicename': ''}
}
chrome_option['mobileemulation']['devicename'] = devicename
else:
'args': ['lang=en_us','--start-maximized'],
'extensions': []
desired_caps_web['goog:chromeoptions']=chrome_option
log.log().logger.info(desired_caps_web)
driver = webdriver.remote.webdriver.webdriver(command_executor=server_url,desired_capabilities=desired_caps_web)
但同样,之前一直正常运行的脚本,到 docker 里不起作用。
看下docker selenium node 节点的log ,发现打印了如下信息:
capabilities are: capabilities {browsername: chrome, chromeoptions: {args: [lang=zh_cn.utf-8], mobileemulation: {devicename: iphone 6}}, goog:chromeoptions: {}, javascriptenabled: true, version: }
多了个 goog:chromeoptions {} 的配置项是怎么回事?
认真看下,capabilities 里我设置的 chromeoptions 已经正确传进来了,但是后面的 goog:chromeoptions: {} 似乎覆盖了对应的配置。
尝试下把脚本里的参数名称从 “chromeoptions ” 改为 “goog:chromeoptions” ,奇迹出现了:
capabilities are: capabilities {browsername: chrome, goog:chromeoptions: {args: [lang=zh_cn.utf-8], mobileemulation: {devicename: iphone 6}}, javascriptenabled: true, version: }
脚本也能正常运行了,对应的浏览器语言、移动设备模拟设置也已生效!
于是修改对应脚本为:
desired_caps_web['goog:chromeoptions']=chrome_option
问题解决!
至此,脚本可以愉快的跑起来了!