当selenium遇上docker

发表时间

docker-selenium 项目以 docker 镜像形式提供了传统的selenium standalone server、web driver、headless 浏览器、VNC server等所有服务,方便了在Linux环境里开展自动化。


更新

Puppeteer 是一种新的UI测试工具,和 selenium相比,更容易开发、更容易docker化。请见Puppeteer系列文章

背景

selenium( 官网链接 )是我们开展web ui 自动化测试的利器,结合webdriver可以很方便的实现自动化代码控制浏览器行为,达到BDD(Behavior-driven development),使开发和测试深入合作,另外也方便测试开展web界面的测试,节约大量的人力。

然而,selenium在实际使用又有些痛处:

  • 往往需要在windows主机上安装、运行被测浏览器,甚至同时安装多种浏览器
  • 浏览器版本难以管理,回退版本麻烦,尤其在自动化时,需要人工参与较多
  • 持续集成时需要配置 windows 节点机
  • 需要为每种浏览器配置 webdriver

所以我们期望有这样的特点:

  • 使用 headless 浏览器,无界面,也就不需要安装
  • 多个版本方便启动和销毁
  • 一体化,减少服务的配置
  • 自带webdriver

在许许多多志愿者的无私努力下,docker-selenium 项目实现了上述这些特点。

docker-selenium项目

docker-selenium项目( 镜像仓库 , 代码仓库 )是将selenium、webdriver、VNC server集成在一个docker镜像里的项目。能提供如下的功能:
  • 代替原有的 remote webdriver
  • 单个容器就能提供全套 selenium+webdriver+headless 浏览器的功能
  • 几个容器配合就能完全代替 selenium grid(目前仅限chrome和firefox)
  • 包含 VNC server,方便远程调试 headless 浏览器
  • 全部在 linux 环境下执行,无需设置 windows 节点机,方便自动化
  • 方便自定义 Dockerfile ,用户可以自己制作镜像

在享用这个项目带来的方便的同时,我们要向那些做出贡献的志愿者致敬,引用代码仓库里的一句话:

The project is made possible by volunteer contributors who have put in thousands of hours of their own time.

如果没有志愿者上千小时的无私奉献,这个项目就无法与您见面。

Standalone 镜像

所有standalone开头的镜像 有这些特点:
  • 包含 selenium server,使用4444端口
  • 包含 headless 浏览器
  • 包含浏览器对应的webdriver

应用场景如下图:

这类镜像应用场合是:不需要远程桌面,节省资源,独立运行

Standalone-debug 镜像

以debug结尾的镜像

有这些特点:
  • 包含 selenium server,使用4444端口
  • 包含 headless 浏览器
  • 包含浏览器对应的webdriver
  • 包含虚拟桌面Xvfb
  • 包含VNC server,使用 5900 端口

这类镜像应用场合是:提供远程桌面,方便调试,一般刚开始搬迁到 docker 时,总会使用这类。等测试稳定了,就可以用上面一种不带 debug 的了

hub 镜像 + node 镜像

相当于将上面的一体化镜像中的 selenium 和浏览器做了分离,方便以一个 hub 控制多个浏览器 node。有这些特点:
  • hub容器对外暴露4444端口,接受请求
  • 每个node应该通过link或者network方式与hub容器建立连接
  • debug结尾的node容器还包含了VNC server供调试

基础镜像

镜像库里除了上面的浏览器外,还有共用的基础镜像,用来生成其他node镜像,不可以直接运行。

但是我们可以从基础镜像的 Dockerfile 里学习到一些细节。

如何使用 Standalone 镜像

我们先看看传统的Remote webdriver是怎么调用的

Python语言

from selenium import webdriver

driver = webdriver.Remote("http://localhost:4444/wd/hub", \
             webdriver.DesiredCapabilities.FIREFOX.copy())
driver.get("http://www.google.com")

Java语言

WebDriver driver = new RemoteWebDriver(
                        new URL("http://localhost:4444/wd/hub"), 
                        DesiredCapabilities.firefox());

UiRecorder 工具

{
    "webdriver": "127.0.0.1:4444"
}

上面三段代码里 webdriver 在4444端口提供服务,接下来我们用 docker 容器替代。

运行 Standalone 镜像

以 standalone-chrome-debug 为例:

$ docker pull selenium/standalone-chrome-debug

然后启动容器,基本命令如下:

$ docker run -d --name chrome --rm \
            -p 4444:4444 \
            -p 5900:5900 \
            selenium/standalone-chrome-debug
上面这条命令的参数含义如下:
  • -d, 表示不附着容器,使容器在后台运行
  • --name 是给容器指定名称 chrome
  • --rm 容器运行结束后即删除,方便调试
  • -p 4444:4444 暴露宿主机的4444端口到容器的4444端口,提供 webdriver 服务;
  • -p 5900:5900 暴露宿主机的5900端口,提供 VNC 远程桌面服务,如果是在 Mac 上运行 docker 容器,有可能5900端口已使用,可以换为5901端口,写法是 -p 5901:5900

查看启动日志

如果不带-d参数运行上面的命令,就能在命令行看到 selenium standalone server 和 xvfb VNC server启动的过程:

Waiting xvfb...
15:28:30.510 INFO - Selenium build info: version: '3.5.0', revision: '8def36e068'
15:28:30.510 INFO - Launching a standalone Selenium Server
......
15:28:30.734:INFO:osjs.Server:main: Started @420ms
15:28:30.734 INFO - Selenium Server is up and running      # 这一步 Selenium 服务已启动
15:28:30 passing arg to libvncserver: -rfbport
15:28:30 passing arg to libvncserver: 5900
15:28:30 -usepw: found /home/seluser/.vnc/passwd
15:28:30 x11vnc version: 0.9.13 lastmod: 2011-08-10  pid: 51
......
15:28:30 X display :99.0 is 32bpp depth=24 true color
15:28:30
15:28:30 Listening for VNC connections on TCP port 5900      # 这一步 VNC 服务工作在5900端口
15:28:30 Listening for VNC connections on TCP6 port 5900
......
15:28:30 screen setup finished.
......

不用改动测试代码, docker 容器代替了原来的 selenium webdriver 服务。

如何使用docker compose启动chrome容器

虽然上面用docker run命令可以方便的启动容器,但是当参数多起来的时候,未免有些不方便,其实可以用docker compose 方便的启动chrome 容器。只需要编写一个docker-compose.yaml文件,例如下面这样:

version: '2'
services:
  chrome: 
    container_name: chrome
    image: path/to/your/images 
    ports: 
      - 4444:4444  # for webdriver 
      - 5901:5900  # for VNC viewer 
    environment: 
      SCREEN_WIDTH: 1920  # set for xvfb 
      SCREEN_HEIGHT: 1080 
    volumes:
      - "/dev/shm:/dev/shm"
    extra_hosts:
      - "some.domain.of.yours:10.0.0.1"
上面yaml文件里,一些参数的解释:
  1. 采用 host 网络模式,直接绑定主机4444和5900端口,不需要在设置ports
  2. 如果主机的这两个端口已经被占用,则不能使用host模式,需要用port指定端口映射
  3. SCREEN_WIDTH 和 SCREEN_HEIGHT 指定虚拟桌面的分辨率
  4. volumes:”/dev/shm:/dev/shm” 当多线程测试时,多个chrome 实例会崩溃退出,这时使用volumes将宿主机的共享内存给容器使用,见 内存问题 一节。
  5. 最后一行的extra_hosts起到一个内部hosts解析功能,方便指向你需要的测试环境主机,上面例子里,在容器内,将 some.domain.of.yours 域名解析为 10.0.0.1,这样你可以放心的在UI测试代码里指定访问 some.domain.of.yours 这个域名。

容器运行起来后,具体的使用将在下一篇 当selenium遇上docker (二) 介绍。

本页面内容采用 署名协议 CC-BY 授权。欢迎转载,请保留原文链接