基于Docker与Selenium Grid的测试技术                        

10.1  Selenium Grid简介

  尽管即将推出的Selenium 4.0对Selenium
Grid的一些新特性进行了说明(截至本书完稿时,Selenium 4.0尚未正式发布),但是从目前看,官方并没有太多详细文档供大家参考,所以本书仍结合目前广泛使用的Selenium
Grid 版本进行讲解。参见官网上的描述,Selenium
Grid是智能代理服务器,允许Selenium将测试命令路由到远程Web浏览器实例,目的是提供一种在多台计算机上并行运行测试的简便方法。使用Selenium
Grid,一台服务器可以充当将JSON格式的测试命令路由到一个或多个已注册Grid节点的中枢,以获得对远程浏览器实例的访问。Selenium
Grid允许我们在多台计算机上并行运行测试,并集中管理不同的浏览器版本和浏览器配置。如图10-1所示,可以看到Selenium Grid主要由Hub和Node两部分构成。可以使用Python、Java、C#等语言编写和测试Selenium脚本,每个Selenium Grid仅有一个Hub,客户端脚本可以指定连接到这个Hub(主控节点或者叫集线器),Hub接收客户端脚本的运行测试请求,同时将这些测试请求分发到已注册的一个或多个节点以执行并收集运行结果。Selenium Grid中可以有一个或多个Node(节点)。作为节点的机器不必与Hub或其他Node具有相同的操作系统或浏览器。换言之,某个Node可能使用的是Windows操作系统,而在Windows操作系统中安装的是Internet Explorer浏览器,另外的Node可能使用的是Linux操作系统、macOS,而它们安装的浏览器可能是Firefox、Safari、Chrome等。这些Node的设置结合测试来讲,就是看想做哪些操作系统和浏览器版本的兼容性测试,在实际工作中请结合测试执行计划和策略进行选择。

图10-1 
Selenium Grid的组件构成

10.2 
基于Docker的Selenium Grid的相关配置

  Docker Hub提供了Selenium Grid的相关镜像文件以供使用,如图10-2所示。

图10-2 
Selenium Grid的相关镜像文件

  这里,我们使用docker pull命令分别将这3个镜像文件拉取下来,对应的拉取命令如下。

docker pull selenium/hub
docker pull selenium/node-chrome
docker pull selenium/node-firefox

  拉取镜像文件到本地后,可以使用docker images命令查看一下相关镜像的信息,如图10-3所示。

图10-3  Selenium Grid的相关镜像信息

  这里我们先测试一下Hub与Node之间的连通性。

  创建并启动Hub容器,如图10-4所示。

图10-4  创建并启动Hub容器

  创建并启动 chromenode容器节点,如图10-5所示。

图10-5  创建并启动chromenode容器节点

  创建并启动 firefoxnode容器节点,如图10-6所示。

图10-6  创建并启动firefoxnode容器节点

  接下来,在本机浏览器的地址栏中输入http://localhost:4444/grid/console并按Enter键,打开Selenium Grid的控制台,出现图10-7所示页面。

图10-7  Selenium Grid的控制台

  从图10-7可知,当前使用的Selenium Grid 版本为3.141.59,连接到Hub的两个Node中,IP地址为172.17.0.4的Linux操作系统使用的是75.0版本的Firefox浏览器,IP地址为172.17.0.3的Linux操作系统使用的是81.0.4044.92版本的Chrome浏览器。默认情况下,Hub使用的是4444端口,而Node在本例中使用的是5555端口。如果在同一个容器中出现端口冲突等情况,则需要根据实际情况进行调整以避免端口冲突情况再次发生。

10.3  基于Docker + Selenium Grid的案例演示

下面结合Bing搜索案例在Chrome和Firefox浏览器中实现兼容性测试。在经过对Selenium、Docker和Selenium Grid相关知识的学习后,你想到了什么?是不是通过使用Docker + SeleniumGrid就能够完成基于不同浏览器的兼容性测试呢?是的,这确实是个好主意。

  但是,为了让Selenium测试脚本在不同的浏览器中运行,又需要做些什么呢?

  在脚本设计上,需要做一些改变。通常情况下,要在脚本运行时指定主机和端口号,使用的脚本如下。

import time
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities driver = webdriver.Remote(
command_executor='http://192.168.1.102:4444/wd/hub',
desired_capabilities=DesiredCapabilities.CHROME)
base_url = 'https://cn.bing.com'
driver.get(base_url)
driver.save_screenshot('chrome.png')
driver.close()

  通常在执行时,只需要指定Hub的地址(http://192.168.1.102:4444/wd/hub)。这里宿主机的IP地址信息如图10-8所示,Hub会将脚本自动分配给Node去执行。

图10-8  宿主机的IP地址信息

  • command_executor:选填参数,可指定远程服务器的URL字符串或自定义远程连接,默认为http://127.0.0.1:4444/wd/hub。
  • desired_capabilities参数:必填参数,可根据情况配置为在启动浏览器会话时请求功能字典。这里我们使用的是DesiredCapabilities.CHROME,对应的源代码如下所示。
class DesiredCapabilities(object):

    """
Set of default supported desired capabilities.
Use this as a starting point for creating a desired capabilities object for
requesting remote webdrivers for connecting to selenium server or selenium grid.
Usage Example::
from selenium import webdriver
selenium_grid_url = "http://198.0.0.1:4444/wd/hub"
capabilities = DesiredCapabilities.FIREFOX.copy()
capabilities['platform'] = "WINDOWS"
capabilities['version'] = "10"
driver = webdriver.Remote(desired_capabilities=capabilities,
command_executor=selenium_grid_url)
Note: Always use '.copy()' on the DesiredCapabilities object to avoid the side
effects of altering the Global class instance.
""" FIREFOX = {
"browserName": "firefox",
"acceptInsecureCerts": True,
} INTERNETEXPLORER = {
"browserName": "internet explorer",
"version": "",
"platform": "WINDOWS",
} EDGE = {
"browserName": "MicrosoftEdge",
"version": "",
"platform": "ANY"
} CHROME = {
"browserName": "chrome",
"version": "",
"platform": "ANY",
} OPERA = {
"browserName": "opera",
"version": "",
"platform": "ANY",
} SAFARI = {
"browserName": "safari",
"version": "",
"platform": "MAC",
} HTMLUNIT = {
"browserName": "htmlunit",
"version": "",
"platform": "ANY",
} HTMLUNITWITHJS = {
"browserName": "htmlunit",
"version": "firefox",
"platform": "ANY",
"javascriptEnabled": True,
} IPHONE = {
"browserName": "iPhone",
"version": "",
"platform": "MAC",
} IPAD = {
"browserName": "iPad",
"version": "",
"platform": "MAC",
} ANDROID = {
"browserName": "android",
"version": "",
"platform": "ANDROID",
} PHANTOMJS = {
"browserName": "phantomjs",
"version": "",
"platform": "ANY",
"javascriptEnabled": True,
} WEBKITGTK = {
"browserName": "MiniBrowser",
"version": "",
"platform": "ANY",
} WPEWEBKIT = {
"browserName": "MiniBrowser",
"version": "",
"platform": "ANY",
}

  从DesiredCapabilities类的源码可知DesiredCapabilities.CHROME是DesiredCapabilities类定义的字典对象。

  这里采用多线程的方式,分别在Chrome和Firefox浏览器中执行Bing搜索业务。

  Grid_Test.py文件的内容如下。

from threading import Thread
from selenium import webdriver
from time import sleep,ctime
from selenium.webdriver.common.by import By def Test_Bing(Host, Browser):
caps = {'browserName': Browser}
driver = webdriver.Remote(command_executor=Host, desired_capabilities=caps)
driver.get('http://www.bing.com')
driver.find_element(By.ID,'sb_form_q').send_keys('异步社区')
driver.find_element(By.ID,'sb_form_go').click()
PicName=Browser+'_result'+'.png'
driver.save_screenshot(PicName)
assert ('没有与此相关的结果' not in driver.page_source)
sleep(2)
driver.close() if __name__ == '__main__':
pcs = {'http://192.168.1.102:4444/wd/hub': 'chrome',
'http://localhost:4444/wd/hub': 'firefox'
}
threads = []
tds=range(len(pcs))
#创建线程
for host, browser in pcs.items():
t = Thread(target=Test_Bing, args=(host, browser))
threads.append(t)
#启动线程
for i in tds:
threads[i].start()
for i in tds:
threads[i].join()

  从上面的脚本可以看到,这里创建了一个名为Test_Bing()的函数,它包含两个参数,分别用来指定主机和浏览器。这个函数的执行意图就是根据远程服务器的URL字符串和传入的浏览器名称字符串,在对应的浏览器中执行搜索业务,且搜索词为“异步社区”。然后对执行结果进行截图,截图的名称为对应浏览器的名称加上_result.png,最后对搜索结果进行断言。需要说明的是,这里进行截图的目的不仅是看一下结果,还要看一下执行过程。在使用Selenium Grid时,由于测试过程中不会出现浏览器,因此看不到执行过程。如果还想看看不同的容器在执行过程中的界面,那么可以使用VNC Viewer连接到对应的容器(但需要下载对应的selenium/node-firefox-debug和selenium/node-chrome- debug镜像文件,以debug结尾的镜像都带有VNC服务器,在本机上安装VNC客户端后即可远程连接。5900端口为VNC Viewer的监听端口,因此做了端口映射),如图10-9和图10-10所示。

图10-9  创建并启动Debug版本的节点容器

图10-10  使用VNC Viewer观察节点容器的脚本执行情况

  事实上,这对于测试工作并没有太多意义,因而不做太多文字赘述。

  主函数定义了一个包含两个元素的字典,这里虽然使用了同一个地址,但采用的是两种不同的表示方式(宿主机的IP地址为192.168.1.102),而localhost也表示宿主机。那么为什么不都用192.168.1.102或localhost呢?这是因为字典的键(key)是不允许重复的。接下来,我们创建了一个线程列表,以pcs字典的键、值作为Test_Bing()函数的参数添加到这个线程列表中,而后启动这个线程列表中的各个线程。

  在运行脚本前,需要保证创建并启动Hub和Node容器(这里应用的是非Debug版本的Node镜像),如图10-11所示。

图10-11  创建并启动Hub和Node容器

  脚本执行完毕后,将会生成chrome_result.png和firefox_result.png两个图片文件,如图10-12所示。

  图10-12  脚本执行完毕后生成的图片文件

  在本次兼容性测试中,这两个浏览器执行了相同的Bing搜索业务,它们的页面展示、布局、内容基本是相同的,但存在两个小的问题。第一个小问题就是在Chrome浏览器中搜索到的结果有855 000条(见图10-13),而在Firefox浏览器中搜索到的结果有859 000条(见图10-14),它们是不一致的。另一个小问题是,Firefox浏览器会显示Sign in和登录图标,而Chrome浏览器没有。从理论上讲,这是两个严重度级别较低的小Bug,建议针对这两个小的差异,与产品及研发人员再确认一下,产品、测试及研发人员应统一、明确需求,明确后再修改需求或代码,使两者保持一致。

图10-13  在Chrome浏览器中搜索到的结果

图10-14  在Firefox浏览器中搜索到的结果

京东:https://item.jd.com/13123910.html

当当:http://product.dangdang.com/29204520.html

答疑解惑群:50788246

《Selenium自动化测试实战:基于Python》之 基于Docker与Selenium Grid的测试技术的更多相关文章

  1. 《Selenium自动化测试实战》新书上市,有需要朋友们可以了解下,欢迎大家多提宝贵意见

    京东:https://item.jd.com/13123910.html当当:http://product.dangdang.com/29204520.html 1. 本书基于 Python 3.8 ...

  2. 《Selenium自动化测试实战:基于Python》Selenium自动化测试框架入门

    第1章  Selenium自动化测试框架入门 1.1  Selenium自动化测试框架概述 说到目前流行的自动化测试工具,相信只要做过软件测试相关工作,就一定听说过Selenium. 图1-1是某企业 ...

  3. 《Selenium自动化测试实战:基于Python》之 Selenium IDE插件的安装与使用

    第3章  Selenium IDE插件的安装与使用 京东:https://item.jd.com/13123910.html 当当:http://product.dangdang.com/292045 ...

  4. python+selenium 自动化测试实战

    一.前言: 之前的文章说过, 要写一篇自动化实战的文章, 这段时间比较忙再加回家过11一直没有更新博客,今天整理一下实战项目的代码共大家学习.(注:项目是针对我们公司内部系统的测试,只能内部网络访问, ...

  5. selenium自动化测试实战——12306铁路官网范例

    一.Selenium介绍 Selenium 是什么?一句话,自动化测试工具.它支持各种浏览器,包括 Chrome,Safari,Firefox 等主流界面式浏览器,如果你在这些浏览器里面安装一个 Se ...

  6. 《Selenium自动化测试实战:基于Python》之 Python与Selenium环境的搭建

    第2章  Python与Selenium环境的搭建 购买链接:  京东:https://item.jd.com/13123910.html  当当:http://product.dangdang.co ...

  7. 第一章 python+selenium自动化测试实战

    @序章 自动化测试是软件测试的主流方向之一: 教程从测试的根本需求出发,讲解如何开展自动化测试. 首先,我们要明白,自动化仅仅是满足我们某种需求的一种工具:没有必要花费时间把它全部弄懂:我们只需要学会 ...

  8. 第一个python&selenium自动化测试实战项目

    说明:本项目采用流程控制思想,未引用unittest&pytest等单元测试框架 一.项目介绍 目的 测试某官方网站登录功能模块可以正常使用 用例 1.输入格式正确的用户名和正确的密码,验证是 ...

  9. python&selenium自动化测试实战项目

    https://www.cnblogs.com/linuxchao/p/linuxchao-python-selenium-demo.html

  10. 用Selenium自动化测试时,让ChromeDriver中不显示“正受到自动测试软件控制”

    背景: 在用Selenium做自动化测试的时候,默认ChromeDriver是会提示“Chrom正受到自动测试软件控制”的.如下图这样.但我们有些场景下,不希望这个提示出现.本文探索了几种语言去掉这个 ...

随机推荐

  1. 使用map方法递归替换组数对象内的某一个值

    const TreeDataSource = (arr) => { // 判断是否是数组 if (!arr || !arr.length > 0) { return } // 将值存入ma ...

  2. mysql8.0.16免安装教程

    Win10下免安装版MySQL8.0.16的安装和配置   1.MySQL8.0.16解压 其中dada文件夹和my.ini配置文件是解压后手动加入的,如下图所示 2.新建配置文件my.ini放在D: ...

  3. .Net Aspire初体验

    今天参加了Post Microsoft Build & AI Day深圳的集会,众多大佬分享了非常优质前沿的技术和实践,实在受益良多,为了消化吸收关于张队分享的.Net Aspire的内容,特 ...

  4. 【牛客刷题】HJ3 明明的随机数

    题目链接 这题有两个要编码解决的问题,首先是去重,其次是排序. 最开始想着就用Java的TreeSet解决了,简单好用,去重排序都一并解决了,编码只需要考虑input的逻辑就可以,代码如下: impo ...

  5. .NET Core学习笔记(6)——UWP略过SSL证书调用SignalR服务

    在前一篇<.NET Core学习笔记(5)--WebAPI从Server端push消息到Client>中,我们简单学习了.NET Core版本SignalR的使用.Sample工程里我们创 ...

  6. CMake构建学习笔记6-giflib库的构建

    前面构建的zlib.libpng.libjpeg和libtiff都提供了CMakeList.txt文件,因此都可以通过CMake进行构建.不过有的依赖库是并没有CMakeList.txt文件,也就是官 ...

  7. JMeter手机app录制

    在移动应用的性能测试中,如何准确.全面地捕捉用户操作并生成可复用的测试脚本,始终是测试工程师面临的一大挑战.而JMeter,作为一款功能强大的开源性能测试工具,不仅在Web测试中表现优异,在手机App ...

  8. 阿里云CTF and 其他

    RE复现 login_system 这个函数就是判断username,点进去发现是线性方程,用z3解 from z3 import * s=Solver() a=[0]*16 for i in ran ...

  9. Pipeline流水线通过git拉取Jenkinsfile报错 error: RPC failed; result=22, HTTP code = 404

    Pipeline流水线通过git拉取Jenkinsfile报错 error: RPC failed; result=22, HTTP code = 404 在学习共享库时使用通过git拉取jenkin ...

  10. 处理英文中的单数复数 (pluralize, singular plural)

    因为英语很烂, 有时候很烦这个. 如果是 hard code 的情况, 如果我不清楚的话就会去这里找 https://www.wordhippo.com/what-is/the-plural-of/l ...