Selenium 核心架构详解

在写这篇文章之前,我对自动化测试工具,Selenium 也是不太了解的,只是大致看过网上一些零星帖子,以为 Selenium 就是装个浏览器,然后通过本地的 WebDriver 库连接到浏览器,通过客户端 WebDriver库代码,就可以控制浏览器进行目标网站的相关操作(自动化测试)。

直到今天,比较全面的研究一番这个工具后,才对 Selenium 有个更全面的了解。

我之前对 Selenium 的理解(开始部分的文字),并不能说不对,但只能说对了一半。

Selenium 的工作机制比 “直接调用 WebDriver库操作浏览器” 要更复杂一些,其中还要涉及到 Java 的运行环境。Java 环境的作用与 Selenium 的核心架构有关。我们可以从 Selenium 的组件分工来说明。

Selenium 的核心组件分工

Selenium 本质上是一个多层架构的自动化工具,主要包含:

  • 浏览器驱动(如 ChromeDriver)

    直接与浏览器交互的二进制程序(不同浏览器有对应驱动,如 ChromeDriver、GeckoDriver),负责接收指令并控制浏览器。

  • Selenium Server/Grid

    用 Java 编写的服务端程序,负责管理驱动、转发指令、协调多浏览器 / 多设备的并行测试等。

  • 客户端库(如 PHP 的 facebook/webdriver)

    各种语言(PHP、Python、Java 等)的 API 封装,用于编写自动化脚本,通过 HTTP 协议与驱动或 Server 通信。

看到此,我们就知道,Selenium 是一个设计完备的架构,我们可以在不同的语言环境下,通过相应代码库对 Selenium 进行驱动。以达到控制浏览器进行,自动化测试的目的。

Java 环境的作用

Java 环境的核心作用是运行 Selenium Server/Grid,而它的必要性取决于你的使用场景:

简单本地测试(可以不需要 Java)

如果你的需求只是,在本地机器上运行,只控制一个浏览器,直接通过驱动程序(如 ChromeDriver)与浏览器交互。这种情况下,确实可以不启动 Selenium Server,直接让 PHP 客户端通过localhost:9515(ChromeDriver 默认端口)与 ChromeDriver 通信,此时不需要 Java 环境

例如:php 代码实现创建 WebDriver 驱动对象,可以直接连接本地浏览器的 9515 端口,直接控制浏览器。

php 复制
$driver = RemoteWebDriver::create(
    'http://localhost:9515',  // 直接连接ChromeDriver的端口
    DesiredCapabilities::chrome()
);

基于分布式多浏览器节点的复杂环境(必须依赖 Java)

但如果需要以下功能,就必须启动 Selenium Server(这是由 Java 编写的,所以需要 Java 运行环境):

  • 远程控制:在另一台机器上运行浏览器(如服务器 A 的 PHP 脚本控制服务器 B 的浏览器)。
  • 并行测试:同时启动多个浏览器实例执行测试(提高效率)。
  • 跨浏览器管理:统一管理 Chrome、Firefox、Edge 等多种驱动。
  • 分布式测试:通过 Selenium Grid 将测试任务分发到多台设备。

此时,Selenium Server 作为 “中间协调者”,需要 Java 环境才能运行,PHP 客户端通过http://localhost:4444(Server 默认端口)与 Server 通信,再由 Server 转发指令给对应驱动。

Docker 环境让 Selenium 架构部署更加方便

Docker 这个容器服务的出现,确实是一个创举。它将环境部署这个麻烦,但是又必须得过程,直接通过镜像的方式完全的省略掉了。如果不是有什么特殊需求,直接用官方发布的镜像就可以直接使用,不用在关注环境配置。

到此我们要说下 Selenium 的镜像有哪些:

  • hub 镜像:selenium/hub

    这个镜像中安装了 java 环境,以及 Selenium Server。客户端通过连接此服务,来控制 Server 控制下的各个浏览器的节点服务。

  • 以 standalone 开头的镜像,如:selenium/standalone-chromeselenium/standalone-firefox

    这是一个独立完整的 Selenium 测试环境,无需依赖其他组件,启动后即可直接接收测试脚本的请求并执行(通过默认端口 4444)。

    容器中组件包括:

    • Selenium Server(作为 “独立服务器” 运行,兼具 hub 和 node 的功能)
    • Chrome 浏览器
    • 匹配版本的 ChromeDriver
  • 以 node 开头的镜像:selenium/node-chromeselenium/node-firefox

    Selenium Grid 中的 “工作节点”,仅负责执行测试任务,不能独立运行,必须配合 selenium/hub 镜像使用。本身不提供 “接收测试请求” 的能力,需要先连接到 Selenium Hub(selenium/hub 镜像)注册,由 hub 分配测试任务。

    容器内组件包括:

    • Chrome 浏览器
    • 匹配版本的 ChromeDriver
    • 节点服务程序(用于与 hub 通信、接收任务)

简单部署示例

想让 hub 控制不同的浏览器节点,需要先启动 hub 服务,在启动 node 节点服务,并且连接到 hub。

bash 复制
# 1. 启动 hub(负责接收请求、分配任务)
docker run -d -p 4444:4444 --name selenium-hub selenium/hub

# 2. 启动 chrome 节点,连接到 hub
docker run -d --link selenium-hub:hub selenium/node-chrome

# (可选)再启动 firefox 节点,实现多浏览器测试
docker run -d --link selenium-hub:hub selenium/node-firefox

部署好之后,我们就可以通过客户端驱动程序,连接到 hub 服务,然后通过发布不同的命令,去操作 hub 下的不同节点进行测试工作。当然以上只是简单的手动启动容器方式进行部署。实际使用过程中,可能涉及到 docker-compose 和 k8s 来控制集群的启动和配置的共享。这个就需要根据具体的业务架构来布置了,这里就不在过多说明了。

相信看了以上内容,你已经对 Selenium 的核心架构有了更加清楚的认识。