您的位置:软件测试 > 开源软件测试 > 开源功能测试工具 > Selenium
selenium结合docker构建分布式测试环境
作者:不再有的年月 发布时间:[ 2017/4/24 11:17:38 ] 推荐标签:Selenium 功能测试

  由于默认的maxSession为5而maxInstances为1,所以取小的一个,node端只运行有一个session的存在,所以我们第二次运行处于阻塞状态!!这些信息我们会在后面对其镜像的构建文件Dockerfile讲解时提到。作者为什么要将maxInstances设置为1?我的理解是:一般用到Grid布局的都是一些比较大型的测试体系,一般环境搭建好了测试脚本写好了保证有一个测试结果好。我们默认的timeout时间是30000S,这个从上面我们hub的启动日志可以看出来,也是说如果hub在30000s内没有执行任何操作会自动切断!这个timeout的时间是相当的长,关于这个timeout的时间长短我觉得与你的testcase有关,比如你在脚本中有个比较耗时的操作例如Sleep(100),睡眠100S再进行后续操作,如果你的timeout设置为30s,那么在30S的时候hub会主动切断这个连接,也是说你后面的用例是不会再执行了....这个是个仁者见仁,智者见智的事情了,但是我觉得把timeout搞长点好点。想要多次调试脚本,大不了我们把maxInstances与maxSession设置数目大点了。实在不行你也可以先docker stop+node 容器的ID,再docker start +node 容器ID好了!
  说了第二个问题的一些看法,我们重点来看看如何解决第一个问题,在解决第一个问题的同时,我们修改一些配置,一并把第二个问题给解决了!!
  我们先来看看selenium/hub与seleniu/node-firefox的源Dockerfile文件,源码的地址为:https://github.com/SeleniumHQ/docker-selenium,你可以下载或clone下来。我们来看看这个项目的结构:

  Base是selenium镜像的基础,里面的Dockerfile除了在Ubuntu镜像的基础上安装了一些工具包,主要工作如下:
  1.还有搭建了一个java运行环境,用来运行后来的selenium-server-standalone-3.3.1.jar
  2.下载了selenium-server-standalone-3.3.1.jar放在容器的/opt/selenium文件夹下
  Hub文件夹里面的Dockerfile是用来build selenium/hub镜像的,是基于上面的Base,主要工作如下:
  1.定义了node启动的一些参数,发现它把里面的timeout参数改成30s了。我并没有pull新的selenium/hub,你们现在pull的可能timeout参数是30s,我的是30000s。
  2.定义了容器启动的脚本entry_point.sh,并把他复制到容器的/opt/bin下
  NodeBase是一切node镜像的基础,我们查看里面的Dockerfile发现它是基于我们上面提到的Base的,主要工作如下:
  1.定义了node容器的启动脚本entry_point.sh并复制到容器的/opt/bin/下。
  NodeFirefox是用来build我们pull下来的selenium/node-firefox它是基于我们上面提到的NodeBase。我们查看它的Dokcerfile文件,发现它的主要工作如下:
  1.下载了版本号为52.0.2的firefox浏览器,并做了一些配置。
  2.下载了GeckoDriver,我们知道高版本的浏览器必须要通过GeckoDriver来启动一个socket,这也是selenium3.0诞生的主要原因。2.0是无法启动高版本的firefox的
  3.设置fire-node的一些启动参数,我们清楚的看到NODE_MAX_INSTANCES 1与ENV NODE_MAX_SESSION 1的配置,所以如何要改变我们问题二的情况,在重新构建镜像的时候,要重新定义这些环境变量了。
  对上面的解释做个说明:
  1.Dockerfile是用来build镜像的。指令为docker build -t 镜像名称  Dockerfile路径,例如:docker build -t selenium/my-firefxo-node . 用当前路径下的Dockerfile文件来创建一个 selenium/my-firefxo-node镜像文件。
  2.Dockerfile一些基础知识可以百度了解,无非是一些shell指令集的大集合。
  说完了这些,我们来解决我们遇到的第一个和第二个问题,思路很简单,对的,是利用的selenium/firefox-node重新构建镜像。
  截图中文乱码的问题我的考虑如下:
  1.docker的Ubuntu版本是没有中文版的,所以我们要下载中文包,并把默认语言配置成中文
  2.仅仅做了1的操作后,我们重新运行build的镜像,发现还是乱码,查阅资料明白可能是firefox必须支持相应的中文字体才可以避免乱码的情况,所以我们终的Dockerfile内容如下:
FROM selenium/node-firefox
#改变node的启动参数
ENV NODE_MAX_INSTANCES 10
ENV NODE_MAX_SESSION 10
# 配置中文
RUN sudo locale-gen zh_CN.UTF-8 &&
sudo DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales
RUN sudo locale-gen zh_CN.UTF-8
ENV LANG zh_CN.UTF-8
ENV LANGUAGE zh_CN:zh
ENV LC_ALL zh_CN.UTF-8
#更新软件包索引
RUN sudo apt-get update -qqy
#安装基本字体
RUN sudo apt-get -qqy --no-install-recommends install
fonts-ipafont-gothic
xfonts-100dpi
xfonts-75dpi
xfonts-cyrillic
xfonts-scalable
#安装文泉驿微米黑字体
RUN sudo apt-get -qqy install ttf-wqy-microhei
&& sudo ln /etc/fonts/conf.d/65-wqy-microhei.conf /etc/fonts/conf.d/69-language-selector-zh-cn.conf
  说到这遇到一个现实的问题是,我们建立了上面的Dokcerfile文件,但是是在windows平台上的,例如我是放在D盘的Sikilu这个文件夹下的,我们docker主机如何访问这个Sikilu文件夹呢?
  首先,我们要明白个道理,docker是不能运行在windows平台,我们能在windows平台使用是因为它运行在Oracle VM VirtualBox里面的!!所以在windows平台搭建docker时给你安装了个VirtualBox虚拟机。这好办了,我们打开这个虚拟机把D盘的Sikilu设置为共享文件夹好了。具体截图如下:

  设置完后,我们重启虚拟机中名称为default这个docker主机。
  我们在Xshell中切换到根目录cd /发现了共享的文件夹:

  我们把上面的Dockerfile放到我们共享的这个文件夹下并切换进去。执行docker build -t selenium/my_node-firefox .
  build的过程可能要点时间终build成功!我们运行docker images

  可以看到我们build的镜像。我们先停掉上面用selenium/node-firefox启动的容器:

  我们运行如下指令:docker run -P -d --link selenium_hub:hub  selenium/my_node-firefox

  由于selenium/my_node-firefox是基于selenium/node-firefox的,所以容器内部也是个版本为50.0的firefox浏览器。但是我们为该容器下载了中文包且下载了相应的字体,改变了firefox浏览器中文乱码的问题,同时改变了firefox node的启动参数,使它能够同时建立10个session!具体数字多少自己更改,当然也可以改其他的启动参数!
  我们运行上面的测试脚本,发现问题能得到有效的解决,当然运行超过10次又阻塞了,原因上面说的很清楚了我们的大session设置了10!
  还有一个问题:我们如何建立其他版本号的node-firefox?上面说了我们pull下来的是50.0的,比如我要构建集群测试每台机器上不同版本的firefox,那么我们要创建不同版本的镜像!
  这边有2中思路,第一种思路想法也简单
  1.下载我们特定版本的浏览器到我们共享的Sikilu文件夹中。
  2.运行我们上面build的selenium/my_node-firefox这个镜像把这个共享的文件夹挂载进去。(-v参数)
  docker run -P  -v /Sikilu/:/Sikilu --link selenium_hub:hub selenium/my_node-firefox
  3.我们删除该容器/opt下的firefox-50.0这个浏览器,同时解压挂载的宿主机Sikilu中的特定版本的firefox到/opt目录
  4.运行rm -rf /usr/bin/firefox
  5.ln -fs /opt/firefox-$FIREFOX_VERSION/firefox /usr/bin/firefox
  6.exit这个容器运行docker commit -m "firefox-47.0.2"  当前容器的ID  镜像名称,例如docker commit -m "firefox-47.0.2"  2d96630b4f07(我们进入的容器id号)  selenium/node-firefox47.0.2(新的镜像名称)
  上面的一系列操作,我们得到了一个特定版本的镜像,下次启动我们run这个镜像可以了。
  第二种思路,在我们新build的selenium/my_node-firefox这个基础新建Dockerfile,重新构建镜像(建议这种方式毕竟高端点...)内容如下:
FROM selenium/my_node-firefox
#指定新构建firefox版本
ARG FIREFOX_VERSION=47.0.2
#删除已存在firefox浏览器
RUN a=$(find /opt/  -name "firefox" |cut -d/ -f 3)&&sudo rm -rf /opt/$a&&sudo rm -rf /usr/bin/firefox
#下载指定版本的浏览器
RUN sudo apt-get update -qqy
&& sudo rm -rf /var/lib/apt/lists/* /var/cache/apt/*
&& sudo wget --no-verbose -O /tmp/firefox.tar.bz2 https://download-installer.cdn.mozilla.net/pub/firefox/releases/$FIREFOX_VERSION/linux-x86_64/en-US/firefox-$FIREFOX_VERSION.tar.bz2
&& sudo tar -C /opt -xjf /tmp/firefox.tar.bz2
&& sudo rm /tmp/firefox.tar.bz2
&& sudo mv /opt/firefox /opt/firefox-$FIREFOX_VERSION
&& sudo ln -fs /opt/firefox-$FIREFOX_VERSION/firefox /usr/bin/firefox
  同样,我们切换到共享的Sikilu文件夹中运行:docker build -t selenium/node-firefox47.0.2  .
  如果网络较慢是特别费时间的,这时候去听音乐去吧,一段时间后建立一个firefox版本为47.0.2的镜像,当我们run这个镜像来启动容器时,注册进hub的是这个版本的浏览器!!
  后一个问题收尾,是我们开始提到的run一个镜像时的--link的参数。
  docker通过link将source container中定义的环境变量全部导入到received container中。我们先来看看上面提到NodeBase文件下的entry_point.sh这个脚本,我们截取关键的一部分:是执行selenium-server-standalone.jar这个jar包的一段:
  xvfb-run -n $SERVERNUM --server-args="-screen 0 $GEOMETRY -ac +extension RANDR"
  java ${JAVA_OPTS} -jar /opt/selenium/selenium-server-standalone.jar
  -role node
  -hub http://$HUB_PORT_4444_TCP_ADDR:$HUB_PORT_4444_TCP_PORT/grid/register
  -nodeConfig /opt/selenium/config.json
  ${SE_OPTS} &
  NODE_PID=$!
  上面的$HUB_PORT_4444_TCP_PORT表示我们hub的端口号,$HUB_PORT_4444_TCP_ADDR这个代表hub的IP地址,这些是怎么来的?其实这个是因为我们使用link参数,docker自动生成这些参数。我们进入到由镜像selenium/my_node-firefox启动的容器(sudo docker exec -it 24c5fb9a649a  /bin/bash),输入env

  发现了这2个字段,其实这个容器的环境变量被分成5个部分,一个部分是ALIASDB_PORT开头的一系列变量,这些变量会有很组,每组变量的命名格式如下:

  其中<alias>是我们source container的别名;<port>是在Dockerfile中使用EXPOSE导出的端口,还有docker run 的时候使用-p导出的端口;<protocol>则是这些端口对应的协议。
  现在明白上文中为什么--link selenium/hub冒号后面为什么要跟hub或者HUB了吧,只有写成这样才会找到HUB_PORT_4444_TCP_PORT与$HUB_PORT_4444_TCP_ADDR这2个变量,免得容器是启动不起来的!!
  到这里结束吧,本来还想多写点关于docker的用法知识。但是打字打的想吐了,可能本文中一些东西说的不清不楚,但是我相信您通过查阅资料一定能得到相应的解决!!

上一页12下一页
软件测试工具 | 联系我们 | 投诉建议 | 诚聘英才 | 申请使用列表 | 网站地图
沪ICP备07036474 2003-2017 版权所有 上海泽众软件科技有限公司 Shanghai ZeZhong Software Co.,Ltd