diff --git a/website_and_docs/content/documentation/grid/applicability.zh-cn.md b/website_and_docs/content/documentation/grid/applicability.zh-cn.md index 337f0da1e320..a17171754333 100644 --- a/website_and_docs/content/documentation/grid/applicability.zh-cn.md +++ b/website_and_docs/content/documentation/grid/applicability.zh-cn.md @@ -19,37 +19,30 @@ aliases: [

{{% /pageinfo %}} -When would you use a Selenium Grid? +什么情况下可以使用 `Selenium Grid` ? -* To run your tests in parallel, against different browser types, browser versions, operating systems -* To reduce the time needed to execute a test suite +* 想要在不同的浏览器类型、浏览器版本和操作系统上并行运行测试时 +* 想要缩短执行测试案例所需的时间 -Selenium Grid runs test suites in parallel against multiple machines (called Nodes). -For large and long-running test suites, this can save minutes, hours, or perhaps days. -This shortens the turnaround time for test results as your application under test (AUT) -changes. +`Selenium Grid` 可以并行地在多台计算机(称为节点)上运行测试案例。对于大型和长时间运行的测试案例,这可以节省几分钟、几小时甚至几天的时间。 -Grid can run tests (in parallel) against multiple different browsers, and it can -run against multiple instances of the same browser. As an example, let's imagine -a Grid with six Nodes. The first machine has Firefox's latest version, -the second has Firefox "latest minus one", the third gets the latest Chrome, and -the remaining three machines are Mac Minis, which allows for three tests to run in -parallel on the latest version of Safari. +这有效的缩短了测试结果的反馈时间,使得在测试的应用程序发生变化时能够更快地得到测试结果。 -Execution time can be expressed as a simple formula: +`Grid` 可以并行地运行测试,支持多种不同的浏览器类型,并且可以同时运行多个相同浏览器的实例。 -```Number of Tests * Average Test Time / Number of Nodes = Total Execution Time``` +举个例子,假设一个拥有六个节点的Grid。第一台计算机拥有Firefox的最新版本,第二台拥有Firefox的上一个版本,第三台运行最新版Chrome,而其余三台机器是Mac Mini,允许在最新版本的Safari上并行运行三个测试。 + +执行时间可以用一个简单的公式来表示: + +```测试次数 × 平均测试时间 / 节点数 = 总执行时间``` 15 * 45s / 1 = 11m 15s // Without Grid 15 * 45s / 5 = 2m 15s // Grid with 5 Nodes 15 * 45s / 15 = 45s // Grid with 15 Nodes 100 * 120s / 15 = 13m 20s // Would take over 3 hours without Grid -As the test suite is executing, the Grid allocates the tests to run against these -browsers as configured in the tests. +在测试案例执行时,`Grid` 会按照测试配置将测试分配到相应的浏览器上运行。 -A configuration such as this can greatly speed up the execution time of even the largest Selenium test suites. +即使对于比较复杂的 `Selenium` 测试案例,这样的配置也可以极大地加快执行时间。 -Selenium Grid is a completely native part of the Selenium project, and is maintained in parallel by the same team -of committers who work in the core Selenium development. Recognizing the importance of test execution speed, Grid -has been a critical part of the Selenium project since the earliest days. +`Selenium Grid` 是 `Selenium` 项目中的重要组成部分,由同一团队的核心Selenium开发人员并行维护。由于意识到测试执行速度的重要性,`Grid` 自设计之初就成为 `Selenium` 项目的关键部分。 diff --git a/website_and_docs/content/documentation/grid/components.zh-cn.md b/website_and_docs/content/documentation/grid/components.zh-cn.md index d64bfecf76f6..580cf5e22de0 100644 --- a/website_and_docs/content/documentation/grid/components.zh-cn.md +++ b/website_and_docs/content/documentation/grid/components.zh-cn.md @@ -19,105 +19,64 @@ aliases: [

{{% /pageinfo %}} +Selenium Grid 4 是对以前版本的彻底重写。除了对性能和标准合规性进行全面改进外,还分解了 `Grid` 的不同功能以反映更现代的计算和软件开发时代。 Selenium Grid 4 专为容器化和云分布式可扩展性而构建,是现代时代的全新解决方案。 -Selenium Grid 4 is a ground-up rewrite from previous versions. In addition to a comprehensive -set of improvements to performance and standards compliance, the different functions of the grid were -broken out to reflect a more modern age of computing and software development. Purpose-build for containerization -and cloud-distributed scalability, Selenium Grid 4 is a wholly new solution for the modern era. - -{{< card header="**Grid Components**" footer="Grid components shown in the fully distributed mode" >}} -![Selenium Grid 4 Components](/images/documentation/grid/components.png "Selenium Grid 4 Components") +{{< card header="**Grid Components**" footer="全分布式展示的Grid组件" >}} +![Selenium Grid 4 组件](/images/documentation/grid/components.png "Selenium Grid 4 Components") {{< /card >}} -## Router - -The **Router** is the entry point of the Grid, receiving all external requests, and forwards them to -the correct component. +## 路由器(Router) -If the **Router** receives a new session request, it will be forwarded to the **New Session Queue**. +**路由器** 是 Grid 的入口点,接收所有外部请求,并将它们转发给正确的组件。 -If the request belongs to an existing session, the **Router** will query the **Session Map** to get -the **Node** ID where the session is running, and then the request will be forwarded directly to the -**Node**. +如果**路由器**收到新的会话请求,它将被转发到**新会话队列**。 -The **Router** balances the load in the Grid by sending the requests to the component that is able -to handle them better, without overloading any component that is not needed in the process. +如果请求属于一个已经存在的session,**路由器**会查询**Session Map**得到session运行所在的**Node** ID,然后将请求直接转发给**Node**。 -## Distributor +**路由器**通过将请求发送到能够更好地处理它们的组件来平衡网格中的负载,而不会使过程中不需要的任何组件过载。 -The **Distributor** has two main responsibilities: +## 分发器(Distributor) -#### Register and keep track of all Nodes and their capabilities +**分发器**有两个主要职责: -A **Node** registers to the **Distributor** by sending a **Node** registration event through -the **Event Bus**. The **Distributor** reads it, and then tries to reach the **Node** via HTTP -to confirm its existance. If the request is successfull, the **Distributor** registers the Node -and keeps track of all **Nodes** capabilities through the **GridModel**. +#### 注册并跟踪所有Node及其功能 -#### Query the New Session Queue and process any pending new session requests +**Node**通过**事件总线**发送**Node**注册事件来注册到**分发器**。**分发器**读取它,然后尝试通过 HTTP 到达**Node**以确认它的存在。如果请求成功,**Distributor**注册节点并通过 **GridModel** 跟踪所有**Node**功能。 -When a new session request is sent to the **Router**, it gets forwarded to the **New Session Queue**, -where it will wait in the queue. The **Distributor** will poll the **New Session Queue** for pending -new session requests, and then finds a suitable **Node** where the session can be created. After the -session has been created, the **Distributor** stores in the **Session Map** the relation between the -session id and **Node** where the session is being executed. +#### 查询新会话队列并处理任何未决的新会话请求 -## Session Map +当一个新的会话请求被发送到**路由器**时,它被转发到**新会话队列**,它将在队列中等待。 **Distributor** 将轮询**新会话队列**以查找未决的新会话请求,然后找到可以创建会话的合适**Node**。会话创建后,**分发器**将会话 ID 与正在执行会话的**Node**之间的关系存储在**会话映射**中。 -The **Session Map** is a data store that keeps the relationship between the session id and the **Node** -where the session is running. It supports the **Router** in the process of forwarding a request to the -**Node**. The **Router** will ask the **Session Map** for the **Node** associated to a session id. +## 会话映射(Session Map) -## New Session Queue +**会话映射** 是一个数据存储,用于保存会话 ID 和运行会话的**Node**之间的关系。它支持**路由器**在将请求转发到**Node**的过程中进行查询。**路由器**将向**会话映射**询问与会话 ID 关联的**Node**。 -The **New Session Queue** holds all the new session requests in a FIFO order. It has configurable -parameters for setting the request timeout and request retry interval (how often the timeout will -be checked). +## 新会话队列(New Session Queue) -The **Router** adds the new session request to the **New Session Queue** and waits for the response. -The **New Session Queue** regularly checks if any request in the queue has timed out, if so the request -is rejected and removed immediately. +**新会话队列**按先进先出的顺序保存所有新会话请求。它具有可配置的参数,用于设置请求超时和请求重试间隔(检查超时的频率)。 -The **Distributor** regularly checks if a slot is available. If so, the **Distributor** polls the -**New Session Queue** for the first matching request. The **Distributor** then attempts to create -a new session. +**路由器**将**新会话请求**添加到**新会话队列**中并等待响应。**新会话队列**定期检查队列中是否有任何请求超时,如果是,则立即拒绝并将其删除。 -Once the requested capabilities match the capabilities of any of the free **Node** slots, the **Distributor** -attempts to get the available slot. If all the slots are busy, the **Distributor** will send the request back -to the queue. If request times out while retrying or adding to the front of the queue, it will be rejected. +**分发器**定期检查是否有可用的插槽。如果有可用的插槽,则**分发器**会轮询**新会话队列**以查找第一个匹配的请求。然后,**分发器**尝试创建**新会话**。 -After a session is created successfully, the **Distributor** sends the session information to the **New Session Queue**, -which then gets sent back to the **Router**, and finally to the client. +一旦请求的功能与任何空闲**Node**插槽的功能匹配,**分发器**将尝试获取可用插槽。如果所有插槽都已忙碌,则**分发器**将将请求发送回队列。如果请求在重试或添加到队列的前面时超时,则会被拒绝。 -## Node +成功创建会话后,**分发器**将会话信息发送到**新会话队列**,该信息然后被发送回**路由器**,最终发送给客户端。 -A Grid can contain multiple **Nodes**. Each **Node** manages the slots for the available browsers of the machine -where it is running. +## 节点(Node) -The **Node** registers itself to the **Distributor** through the **Event Bus**, and its configuration is sent as -part of the registration message. +一个`Grid`可以包含多个**Node**。每个**Node**管理它所在机器上可用浏览器的插槽。 -By default, the **Node** auto-registers all browser drivers available on the path of the machine where it runs. -It also creates one slot per available CPU for Chromium based browsers and Firefox. For Safari, only one slot is -created. Through a specific [configuration]({{< ref "/configuration" >}}), it can run sessions in Docker -containers or relay commands. +**Node**通过**事件总线**向**分发器**注册自己,并将其配置作为注册消息发送。 -A **Node** only executes the received commands, it does not evaluate, make judgments, or control anything other -than the flow of commands and responses. The machines where the **Node** is running does not need to have the -same operating system as the other components. For example, A Windows **Node** might have the capability of -offering IE Mode on Edge as a browser option, whereas this would not be possible on Linux or Mac, and a Grid can -have multiple **Nodes** configured with Windows, Mac, or Linux. +默认情况下,**Node**会自动注册其所在机器上路径中可用的所有浏览器驱动程序。它还为基于Chromium的浏览器和Firefox创建每个可用CPU一个插槽。对于Safari,只创建一个插槽。通过特定的[配置]({{< ref "/configuration" >}}),它可以在Docker容器中运行会话或转发命令。 -## Event Bus +**Node**仅执行接收到的命令,不评估、不做出判断或控制任何除命令和响应流之外的东西。**Node**所在的机器不需要与其他组件具有相同的操作系统。例如,Windows节点可能具有在Edge上提供IE模式作为浏览器选项的能力,而在Linux或Mac上则不可能,网格可以配置多个具有Windows、Mac或Linux的**Node**。 -The **Event Bus** serves as a communication path between the **Nodes**, **Distributor**, **New Session Queue**, -and **Session Map**. The Grid does most of its internal communication through messages, avoiding expensive HTTP -calls. When starting the Grid in its fully distributed mode, the **Event Bus** is the first component that -should be started. +## 事件总线(Event Bus) +**事件总线**作为**节点**、**分发器**、**新会话队列**和**会话映射**之间的通信路径。`Grid` 的大部分内部通信都通过消息进行,避免了频繁的HTTP调用。在完全分布式模式下启动`Grid` 时,**事件总线**应该是第一个组件。 -{{% alert title="Running your own Grid" color="primary" %}} -Looking forward to using all these components and run your own Grid? -Head to the ["Getting Started"]({{< ref "getting_started.md" >}}) -section to understand how to put all these pieces together. +{{% alert title="运行自己的Grid" color="primary" %}} +想要使用所有这些组件并运行自己的网格?请前往["入门"]({{< ref "getting_started.md" >}})部分了解如何将所有这些部分组合在一起。 {{% /alert %}} diff --git a/website_and_docs/content/documentation/grid/getting_started.zh-cn.md b/website_and_docs/content/documentation/grid/getting_started.zh-cn.md index 73c0bab29121..b297dac50cf8 100644 --- a/website_and_docs/content/documentation/grid/getting_started.zh-cn.md +++ b/website_and_docs/content/documentation/grid/getting_started.zh-cn.md @@ -20,88 +20,78 @@ aliases: [

{{% /pageinfo %}} -## Quick start - -1. Prerequisites - * Java 11 or higher installed - * Browser(s) installed - * Browser driver(s) - * If using Selenium 4.6, Selenium Manager will configure the drivers for Chrome, Firefox, and Edge [if they are not found on the `PATH`]({{< ref "../webdriver/getting_started/install_drivers.md#1-selenium-manager-smallbetasmall" >}}). - * [Installed and on the `PATH`]({{< ref "../webdriver/getting_started/install_drivers.md#3-path-环境变量" >}}) - * Download the Selenium Server jar file from the [latest release](https://github.com/SeleniumHQ/selenium/releases/latest) -1. Start the Grid +## 快速开始 + +1. 先决条件 + * 需要安装 Java 11 或更高版本 + * 需要安装浏览器 + * 需要安装浏览器驱动程序 + * 如果使用 Selenium 4.6,Selenium Manager 将为 Chrome、Firefox 和 Edge 配置驱动程序[(如果它们在 PATH 上找不到)]({{< ref "../webdriver/getting_started/install_drivers.md#1-selenium-manager-smallbetasmall" >}}). + * [需要已经安装并配置了 PATH 环境变量]({{< ref "../webdriver/getting_started/install_drivers.md#3-path-环境变量" >}}) + * 从[最新的发布版本](https://github.com/SeleniumHQ/selenium/releases/latest)下载 Selenium Server jar 文件 +1. 启动 Grid * `java -jar selenium-server-.jar standalone` -1. Point* your WebDriver tests to [http://localhost:4444](http://localhost:4444) -1. (Optional) Check running tests and available capabilities by opening your browser at [http://localhost:4444](http://localhost:4444) +1. 将您的 WebDriver 测试指向 [http://localhost:4444](http://localhost:4444) +1. (可选) 通过在浏览器中打开 [http://localhost:4444](http://localhost:4444) 检查正在运行的测试和可用的功能 -*Wondering how to point your tests to [http://localhost:4444](http://localhost:4444)? -Check the [`RemoteWebDriver` section]({{< ref "../webdriver/drivers/#远程驱动" >}}). +*想知道如何将您的测试指向 [http://localhost:4444](http://localhost:4444)吗? +请查看 [`RemoteWebDriver` section]({{< ref "../webdriver/drivers/#远程驱动" >}})。 -To learn more about the different configuration options, go through the sections below. +要了解更多不同的配置选项,请查看以下各小节。 -## Grid roles +## Grid 角色 -Grid is composed by six different [components]({{< ref "components.md" >}}), which gives -you the option to deploy it in different ways. +Grid由六个不同的[组件]({{< ref "components.md" >}})组成,这使您可以以不同的方式部署它。 -Depending on your needs, you can start each one of them on its own (Distributed), group -them in Hub & Node, or all in one on a single machine (Standalone). +根据您的需求,您可以单独启动每个组件(分布式),将它们分组为Hub和Node,或者全部在单个机器上运行(独立)。 -### Standalone +### 单机部署(Standalone) -**Standalone** combines all Grid [components]({{< ref "components.md" >}}) seamlessly -into one. Running a Grid in **Standalone** mode gives you a fully functional Grid -with a single command, within a single process. **Standalone** can only run on a -single machine. +**Standalone** 可以将所有 Grid [组件]({{< ref "components.md" >}}) 无缝地整合成一个单独的实体。在 **Standalone** 模式下运行 Grid,只需一个命令即可获得一个完整的 Grid,并在一个进程中运行。**Standalone** 只能在一台机器上运行。 -**Standalone** is also the easiest mode to spin up a Selenium Grid. By default, the server -will listen for `RemoteWebDriver` requests on [http://localhost:4444](http://localhost:4444). -By default, the server will detect the available drivers that it can use from the System -[`PATH`]({{< ref "../webdriver/getting_started/install_drivers.md#3-path-环境变量" >}}). +**Standalone** 模式也是最容易启动 Selenium Grid 的模式。默认情况下,服务器将在 [http://localhost:4444](http://localhost:4444) 上监听 `RemoteWebDriver` 请求,并且服务器将从系统 [PATH]({{< ref "../webdriver/getting_started/install_drivers.md#3-path-环境变量" >}}) 中检测可以使用的驱动程序。 ```shell java -jar selenium-server-.jar standalone ``` -After starting successfully the Grid in Standalone mode, point your WebDriver tests -to [http://localhost:4444](http://localhost:4444). - -Common use cases for **Standalone** are: -* Develop or debug tests using `RemoteWebDriver` locally -* Running quick test suites before pushing code -* Have a easy to setup Grid in a CI/CD tool (GitHub Actions, Jenkins, etc...) +成功启动 Standalone 模式的 Grid 后,将你的 WebDriver 测试指向 [http://localhost:4444](http://localhost:4444)。 +**Standalone** 的常见用途包括: +* 本地使用 `RemoteWebDriver` 开发或调试测试 +* 推送代码之前运行快速测试套件 +* 在 CI/CD 工具(GitHub Actions、Jenkins 等)中设置简单的 Grid ### Hub and Node -**Hub and Node** is the most used role because it allows to: -* Combine different machines in a single Grid - * Machines with different operating systems and/or browser versions, for example -* Have a single entry point to run WebDriver tests in different environments -* Scaling capacity up or down without tearing down the Grid +**Hub和Node**是最常用的角色,因为它允许: +* 将不同的机器组合成一个单一的Grid + * 例如拥有不同操作系统和/或浏览器版本的机器 +* 在不同的环境中运行WebDriver测试有一个单一的入口点 +* 在不破坏Grid的情况下增加或减少容量。 #### Hub -A Hub is composed by the following [components]({{< ref "components.md" >}}): -Router, Distributor, Session Map, New Session Queue, and Event Bus. +一个Hub由以下[组件]({{< ref "components.md" >}})组成: +路由器(Router)、分发器(Distributor)、会话映射(Session Map)、新会话队列(New Session Queue)和事件总线(Event Bus)。 ```shell java -jar selenium-server-.jar hub ``` -By default, the server will listen for `RemoteWebDriver` requests on [http://localhost:4444](http://localhost:4444). +默认情况下,服务器将在 [http://localhost:4444](http://localhost:4444) 上监听`RemoteWebDriver`请求。 #### Node -During startup time, the **Node** will detect the available drivers that it can use from the System -[`PATH`]({{< ref "../webdriver/getting_started/install_drivers.md#3-path-环境变量" >}}). +在启动时,**Node**将从系统的[`PATH`]({{< ref "../webdriver/getting_started/install_drivers.md#3-path-环境变量" >}})中检测可用的驱动程序。 + +以下命令假设**Node**正在运行的机器与**Hub**在同一台机器上。 -The command below assumes the **Node** is running on the same machine where the **Hub** is running. ```shell java -jar selenium-server-.jar node ``` -##### More than one Node on the same machine +##### 同一台机器上的多个Node **Node** 1 ```shell @@ -113,90 +103,88 @@ java -jar selenium-server-.jar node --port 5555 java -jar selenium-server-.jar node --port 6666 ``` -##### Node and Hub on different machines +##### 不同机器上的Node和Hub + +**Hub**和**Nodes**通过HTTP和[**事件总线**]({{< ref "components.md#event-bus" >}})(**事件总线**位于**Hub**内部)进行通信。 -**Hub** and **Nodes** talk to each other via HTTP and the [**Event Bus**]({{< ref "components.md#event-bus" >}}) -(the **Event Bus** lives inside the **Hub**). A **Node** sends a message to the **Hub** via the **Event Bus** to -start the registration process. When the **Hub** receives the message, reaches out to the **Node** via HTTP to -confirm its existence. +**Node**通过事件总线向**Hub**发送消息以开始注册过程。当**Hub**收到消息时,通过HTTP与**Node**联系以确认其存在。 -To successfully register a **Node** to a **Hub**, it is important to expose the **Event Bus** ports (4442 and 4443 by -default) on the **Hub** machine. This also applies for the **Node** port. With that, both **Hub** and **Node** will -be able to communicate. +要成功将**Node**注册到**Hub**,重要的是要在**Hub**机器上公开**事件总线**端口(默认为4442和4443)。这也适用于**Node**端口。有了这个,**Hub**和**Node**都能够通信。 -If the **Hub** is using the default ports, the `--hub` flag can be used to register the **Node** +如果**Hub**使用默认端口,则可以使用 `--hub` 注册**Node**。 ```shell java -jar selenium-server-.jar node --hub http://:4444 ``` -When the **Hub** is not using the default ports, the `--publish-events` and `--subscribe-events` flags are needed. +当**Hub**未使用默认端口时,需要使用`--publish-events`和`--subscribe-events`。 -For example, if the **Hub** uses ports `8886`, `8887`, and `8888` +例如,如果**Hub**使用端口8886、8887和8888。 ```shell java -jar selenium-server-.jar hub --publish-events tcp://:8886 --subscribe-events tcp://:8887 --port 8888 ``` -The **Node** needs to use those ports to register successfully +**Node**需要使用这些端口才能成功注册。 ```shell java -jar selenium-server-.jar node --publish-events tcp://:8886 --subscribe-events tcp://:8887 ``` -### Distributed +### 分部署部署(Distributed) -When using a Distributed Grid, each component is started separately, and ideally on different machines. +在使用分布式Grid时,每个组件都需要单独启动,并且理想情况下应该在不同的机器上。 {{% alert color="primary" %}} -It is important to expose all ports properly in order to allow fluent communication between all components. +重要的是要正确暴露所有端口,以允许所有组件之间的流畅通信。 {{% /alert %}} -1. **Event Bus**: enables internal communication between different Grid components. +1. **事件总线(Event Bus)**: 使不同网格组件之间的内部通信成为可能。 -Default ports are: `4442`, `4443`, and `5557`. +默认端口为:`4442`、`4443`和`5557`。 ```shell java -jar selenium-server-.jar event-bus --publish-events tcp://:4442 --subscribe-events tcp://:4443 --port 5557 ``` -2. **New Session Queue**: adds new session requests to a queue, which will be queried by the Distributor +2. **新会话队列(New Session Queue)**: 将新的会话请求添加到一个队列中,Distributor将查询该队列。 -Default port is `5559`. +默认端口为`5559`。 ```shell java -jar selenium-server-.jar sessionqueue --port 5559 ``` -3. **Session Map**: maps session IDs to the **Node** where the session is running +3. **会话映射(Session Map)**: 将会话ID映射到运行该会话的节点。 + +默认**会话映射**端口为`5556`。**会话映射**与**事件总线**进行交互。 -Default **Session Map** port is `5556`. **Session Map** interacts with the **Event Bus**. ```shell java -jar selenium-server-.jar sessions --publish-events tcp://:4442 --subscribe-events tcp://:4443 --port 5556 ``` -4. **Distributor**: queries the **New Session Queue** for new session requests, and assigns them to a **Node** when the capabilities match. **Nodes** register to the **Distributor** the way they register to the **Hub** in a **Hub/Node** Grid. +4. **分配器(Distributor)**: 查询新 **会话队列(New Session Queue)** 以获取新会话请求,并在能力匹配时将其分配给 **Node**。 **Nodes** 注册到 **Distributor** 的方式与在 **Hub/Node** 网格中注册到 **Hub** 相同。 -Default **Distributor** port is `5553`. **Distributor** interacts with **New Session Queue**, **Session Map**, **Event Bus**, and the **Node(s)**. +默认**分配器**端口为`5553`。**分配器** 与 **新会话队列**、**会话映射**、**事件总线** 和 **Node(s)** 进行交互。 ```shell java -jar selenium-server-.jar distributor --publish-events tcp://:4442 --subscribe-events tcp://:4443 --sessions http://:5556 --sessionqueue http://:5559 --port 5553 --bind-bus false ``` -5. **Router**: redirects new session requests to the queue, and redirects running sessions requests to the **Node** running that session. +5. **路由器(Router)**: 将新会话请求重定向到队列,并将正在运行的会话请求重定向到运行该会话的**Node**。 + +默认**路由器**端口为`4444`。**路由器** 与 **新会话队列**、**会话映射**和**分配器** 进行交互。 -Default **Router** port is `4444`. **Router** interacts with **New Session Queue**, **Session Map**, and **Distributor**. ```shell java -jar selenium-server-.jar router --sessions http://:5556 --distributor http://:5553 --sessionqueue http://:5559 --port 4444 ``` 6. **Node(s)** -Default **Node** port is `5555`. +默认 **Node** 端口是 `5555`. ```shell java -jar selenium-server-.jar node --publish-events tcp://:4442 --subscribe-events tcp://:4443 ``` -## Metadata in tests +## 测试中的 Metadata -Add metadata to your tests and consume it via [GraphQL]({{< ref "advanced_features/graphql_support.md" >}}) -or visualize parts of it (like `se:name`) through the Selenium Grid UI. +向测试中添加 `Metadata` 并通过[GraphQL]({{< ref "advanced_features/graphql_support.md" >}})进行消费,或通过 `Selenium Grid UI` 可视化其部分内容(例如`se:name`)。 -Metadata can be added by prefixing a capability with `se:`. Here is a quick example in Java showing that. +可以通过在 `capability` 前加上 `se:` 来添加元数据。以下是一个Java的快速示例。 ```java ChromeOptions chromeOptions = new ChromeOptions(); @@ -212,115 +200,83 @@ driver.get("http://www.google.com"); driver.quit(); ``` -## Querying Selenium Grid +## 查询 Selenium Grid 相关状态 -After starting a Grid, there are mainly two ways of querying its status, through the Grid -UI or via an API call. +启动 `Grid` 后,主要有两种方式查询其状态,通过 `Grid UI` 或通过 `API` 调用。 -The Grid UI can be reached by opening your preferred browser and heading to -[http://localhost:4444](http://localhost:4444). +可以通过打开您喜欢的浏览器并前往[http://localhost:4444](http://localhost:4444)。 -API calls can be done through the [http://localhost:4444/status](http://localhost:4444/status) -endpoint or using [GraphQL]({{< ref "advanced_features/graphql_support.md" >}}) +`API` 调用可以通过 [http://localhost:4444/status](http://localhost:4444/status) 端点或使用 [GraphQL]({{< ref "advanced_features/graphql_support.md" >}}) {{% pageinfo color="primary" %}} -For simplicity, all command examples shown in this page assume that components are running -locally. More detailed examples and usages can be found in the -[Configuring Components]({{< ref "/configuration" >}}) section. +为简单起见,本页中显示的所有命令示例均假定组件正在运行在本地。更详细的示例和用法可以在[配置组件]({{< ref "/configuration" >}}) 部分。 {{% /pageinfo %}} -## Using the Java 11 HTTP Client {{% badge-version version="4.5" %}} +## 使用 Java 11 中的 HTTP Client {{% badge-version version="4.5" %}} + +默认情况下,Grid 将使用 [AsyncHttpClient](https://github.com/AsyncHttpClient/async-http-client)。 AsyncHttpClient 是一个建立在 Netty 之上的开源库。 它允许异步执行 HTTP 请求和响应。 此外,它还提供 WebSocket 支持。 因此它很合适。 -By default, Grid will use [AsyncHttpClient](https://github.com/AsyncHttpClient/async-http-client). -AsyncHttpClient is an open-source library built on top of Netty. It allows the execution of HTTP -requests and responses asynchronously. Additionally it also provides WebSocket support. Hence it -is a good fit. +然而,AsyncHttpClient 从 2021 年 6 月开始就没有主动维护了。恰逢 Java 11+ 提供了内置的 HTTP 和 WebSocket 客户端。 -However, AsyncHttpClient is not been actively maintained since June 2021. It coincides with the -fact that Java 11+ provides a built-in HTTP and WebSocket client. Currently, Selenium -has plans to upgrade the minimum version supported to Java 11. However, it is a sizeable effort. -Aligning it with major releases and accompanied announcements is crucial to ensure the user -experience is intact. +目前,Selenium 计划将支持的最低版本升级到 Java 11。然而,这需要大量的工作。为了确保用户体验不受影响,将其与主要发布版本和相应的公告对齐是至关重要的。 -To do use the Java 11 client, you will need to download the `selenium-http-jdk-client` jar file -and use the `--ext` flag to make it available in the Grid jar's classpath. +要使用 Java 11 客户端,您需要下载 `selenium-http-jdk-client` jar文件并使用 `--ext` 参数使其在 Grid jar 的类路径中可用。 -The jar file can be downloaded directly from [repo1.maven.org](https://repo1.maven.org/maven2/org/seleniumhq/selenium/selenium-http-jdk-client/) -and then start the Grid in the following way: +jar文件可以直接从 [repo1.maven.org](https://repo1.maven.org/maven2/org/seleniumhq/selenium/selenium-http-jdk-client/) 下载,然后使用以下方式启动Grid: ```bash java -Dwebdriver.http.factory=jdk-http-client -jar selenium-server-.jar --ext selenium-http-jdk-client-.jar standalone ``` -An alternative to downloading the `selenium-http-jdk-client` jar file is to use [Coursier](https://get-coursier.io/docs/cli-installation). +下载 `selenium-http-jdk-client` jar 文件的替代方法是使用 [Coursier](https://get-coursier.io/docs/cli-installation)。 ```bash java -Dwebdriver.http.factory=jdk-http-client -jar selenium-server-.jar --ext $(coursier fetch -p org.seleniumhq.selenium:selenium-http-jdk-client:) standalone ``` -If you are using the Hub/Node(s) mode or the Distributed mode, setting the `-Dwebdriver.http.factory=jdk-http-client` -and `--ext` flags needs to be done for each one of the components. +如果您使用的是集线器/节点模式或分布式模式,则需要为每个组件设置 `-Dwebdriver.http.factory=jdk-http-client` 和 `--ext` 参数。 -## Grid sizes +## Grid 的规模 -Choosing a Grid role depends on what operating systems and browsers need to be supported, -how many parallel sessions need to be executed, the amount of available machines, and how -powerful (CPU, RAM) those machines are. +选择 `Grid` 角色取决于需要支持什么操作系统和浏览器、需要执行多少个并行会话、可用机器的数量以及这些机器的配置(CPU、RAM)。 -Creating sessions concurrently relies on the available processors to the **Distributor**. -For example, if a machine has 4 CPUs, the **Distributor** will only be able to create up -to 4 sessions concurrently. +并发创建会话依赖于 **分配器** 的可用处理器。 例如,如果一台机器有 4 个 CPU,则 **分配器** 最多只能同时创建 4 个会话。 -By default, the maximum amount of concurrent sessions a **Node** supports is limited by -the number of CPUs available. For example, if the **Node** machine has 8CPUs, it can run -up to 8 concurrent browser sessions (with the exception of Safari, which is always one). -Additionally, it is expected that each browser session should use around 1GB RAM. +默认情况下,**Node** 支持的最大并发会话数受可用 CPU 数量的限制。 例如,如果 **Node** 机器有 8 个 CPU,它最多可以运行 8 个并发浏览器会话(Safari 除外,它始终是一个)。 此外,预计每个浏览器会话应使用大约 1GB 的 RAM。 -In general, it is a recommended to have **Nodes** as small as possible. Instead of having -a machine with 32CPUs and 32GB RAM to run 32 concurrent browser sessions, it is better to -have 32 small **Nodes** in order to better isolate processes. With this, if a **Node** -fails, it will do it in an isolated way. Docker is a good tool to achieve this approach. +通常,建议 **Nodes** 尽可能小。 与其让机器有 32 个 CPU 和 32GB RAM 来运行 32 个并发浏览器会话,不如有 32 个小的 **Node**,以便更好地隔离进程。 有了这个,如果一个 **Node** 发生故障,它将以孤立的方式进行。 Docker 是实现这种方法的好工具。 -Note that the default values (1CPU/1GB RAM per browser) are a recommendation and they could -not apply to your context. It is recommended to use them as a reference, but measuring -performance continuously will help to determine the ideal values for your environment. +请注意,默认值(每个浏览器 1 个 CPU/1GB RAM)是建议值,它们不适用于您的上下文。 建议将它们用作参考,但持续测量性能将有助于确定您的环境的理想值。 -Grid sizes are relative to the amount of supported concurrent sessions and amount of -**Nodes**, and there is no "one size fits all". Sizes mentioned below are rough estimations -thay can vary between different environments. For example a **Hub/Node** with 120 **Nodes** -might work well when the **Hub** has enough resources. Values below are not set on stone, -and feedback is welcomed! +`Grid` 大小与支持的并发会话数量和 **Node** 数量有关,没有“一刀切”的说法。 下面提到的尺寸是粗略的估计,不同环境之间可能会有所不同。 例如,当 **Hub** 具有足够的资源时,具有 120 个 **Nodes** 的 **Hub/Node** 可能运行良好。 以下值并非一成不变,欢迎提供反馈! -### Small +### 小规模 -**Standalone** or **Hub/Node** with 5 or less **Nodes**. +**Standalone** 或 **Hub/Node** 不超过5个 **Nodes**. -### Middle +### 中等规模 -**Hub/Node** between 6 and 60 **Nodes**. +**Hub/Node** 介于6到60个 **Nodes** 之间。 -### Large +### 大规模 -**Hub/Node** between 60 and 100 **Nodes**. **Distributed** with over 100 **Nodes**. +**Hub/Node** 介于60到100个 **Nodes** 之间, **Distributed** 超过100个 **Nodes**。 -## Warning +## 请注意 -Selenium Grid must be protected from external access using appropriate -firewall permissions. +必须使用适当的防火墙权限保护Selenium Grid免受外部访问。 -Failure to protect your Grid could result in one or more of the following occurring: +以下一种或多种情况可能会导致你的 `Grid` 处于一个不安全的状态: -* You provide open access to your Grid infrastructure -* You allow third parties to access internal web applications and files -* You allow third parties to run custom binaries +* 您提供对您的 `Grid` 基础设施的开放访问 +* 您允许第三方访问内部网络应用程序和文件 +* 您允许第三方运行自定义二进制文件 -See this blog post on [Detectify](//labs.detectify.com), which gives a good -overview of how a publicly exposed Grid could be misused: -[Don't Leave your Grid Wide Open](//labs.detectify.com/2017/10/06/guest-blog-dont-leave-your-grid-wide-open/) +请参阅 [Detectify](//labs.detectify.com) 上的这篇博文,它提供了一个很好的公开暴露的 `Grid` 如何被滥用的概述:[不要让你的 `Grid` 暴露在外](//labs.detectify.com/2017/10/06/guest-blog-dont-leave-your-grid-wide-open/) -## Further reading +## 延伸阅读 -* [Components]({{< ref "components.md" >}}): learn how Grid's internal components relate to each other. -* [Configuration]({{< ref "/configuration" >}}): customize your Grid setup. -* [Architecture]({{< ref "architecture.md" >}}): understand key concepts in Grid. -* [Advanced Features]({{< ref "/advanced_features" >}}): explore more possibilities through Grid's features. +* [Components]({{< ref "components.md" >}}):了解 `Grid` 的内部组件如何相互关联。 +* [Configuration]({{< ref "/configuration" >}}): 自定义您的 `Grid` 设置。 +* [Architecture]({{< ref "architecture.md" >}}): 理解 `Grid` 中的关键概念。 +* [Advanced Features]({{< ref "/advanced_features" >}}): 通过Grid的特性探索更多的可能性。 diff --git a/website_and_docs/content/documentation/webdriver/interactions/windows.zh-cn.md b/website_and_docs/content/documentation/webdriver/interactions/windows.zh-cn.md index e35b58ed4d66..fa5c5c85054c 100644 --- a/website_and_docs/content/documentation/webdriver/interactions/windows.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/interactions/windows.zh-cn.md @@ -47,9 +47,11 @@ driver.findElement(By.linkText("new window")).click(); wait.until(numberOfWindowsToBe(2)); // 循环执行,直到找到一个新的窗口句柄 -for (String windowHandle : driver.getWindowHandles()) {if(!originalWindow.contentEquals(windowHandle)) {driver.switchTo().window(windowHandle); -break; -} +for (String windowHandle : driver.getWindowHandles()) { + if(!originalWindow.contentEquals(windowHandle)) { + driver.switchTo().window(windowHandle); + break; + } } // 等待新标签完成加载内容 @@ -324,11 +326,12 @@ driver.switchTo().window(originalWindow) /** * 使用 JUnit 的例子 * https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/AfterAll.html - */ - @AfterAll - public static void tearDown() {driver.quit(); - } - {{< /tab >}} +*/ +@AfterAll +public static void tearDown() { + driver.quit(); +} +{{< /tab >}} {{< tab header="Python" >}} # unittest teardown # https://docs.python.org/3/library/unittest.html?highlight=teardown#unittest.TestCase.tearDown @@ -365,11 +368,12 @@ end /** * 使用 JUnit 的例子 * https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/AfterAll.html - */ - @AfterAll - fun tearDown() {driver.quit() - } - {{< /tab >}} +*/ +@AfterAll +fun tearDown() { + driver.quit() +} +{{< /tab >}} {{< /tabpane >}} 如果不在测试上下文中运行 WebDriver,您可以考虑使用 `try / finally`,这是大多数语言都提供的, @@ -377,7 +381,10 @@ end {{< tabpane langEqualsHeader=true >}} {{< tab header="Java" >}} -try {//WebDriver 代码…} finally {driver.quit(); +try { + //WebDriver 代码… +} finally { + driver.quit(); } {{< /tab >}} {{< tab header="Python" >}} @@ -652,13 +659,13 @@ import java.io.*; import org.openqa.selenium.*; public class SeleniumTakeScreenshot { -public static void main(String args[]) throws IOException { -WebDriver driver = new ChromeDriver(); -driver.get("http://www.example.com"); -File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); -FileUtils.copyFile(scrFile, new File("./image.png")); -driver.quit(); -} + public static void main(String args[]) throws IOException { + WebDriver driver = new ChromeDriver(); + driver.get("http://www.example.com"); + File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); + FileUtils.copyFile(scrFile, new File("./image.png")); + driver.quit(); + } } {{< /tab >}} {{< tab header="Python" >}} @@ -745,13 +752,13 @@ import java.io.IOException; public class SeleniumelementTakeScreenshot { public static void main(String args[]) throws IOException { -WebDriver driver = new ChromeDriver(); -driver.get("https://www.example.com"); -WebElement element = driver.findElement(By.cssSelector("h1")); -File scrFile = element.getScreenshotAs(OutputType.FILE); -FileUtils.copyFile(scrFile, new File("./image.png")); -driver.quit(); -} + WebDriver driver = new ChromeDriver(); + driver.get("https://www.example.com"); + WebElement element = driver.findElement(By.cssSelector("h1")); + File scrFile = element.getScreenshotAs(OutputType.FILE); + FileUtils.copyFile(scrFile, new File("./image.png")); + driver.quit(); + } } {{< /tab >}} {{< tab header="Python" >}} @@ -911,14 +918,14 @@ _注意: 此功能需要无头模式下的Chromium浏览器_ {{< tab header="Java" >}} import org.openqa.selenium.print.PrintOptions; - driver.get("https://www.selenium.dev"); - printer = (PrintsPage) driver; +driver.get("https://www.selenium.dev"); +printer = (PrintsPage) driver; - PrintOptions printOptions = new PrintOptions(); - printOptions.setPageRanges("1-2"); +PrintOptions printOptions = new PrintOptions(); +printOptions.setPageRanges("1-2"); - Pdf pdf = printer.print(printOptions); - String content = pdf.getContent(); +Pdf pdf = printer.print(printOptions); +String content = pdf.getContent(); {{< /tab >}} {{< tab header="Python" >}} from selenium.webdriver.common.print_page_options import PrintOptions diff --git a/website_and_docs/content/documentation/webdriver/troubleshooting/errors.zh-cn.md b/website_and_docs/content/documentation/webdriver/troubleshooting/errors.zh-cn.md index 050b541ec3f6..cafe1ec99efb 100644 --- a/website_and_docs/content/documentation/webdriver/troubleshooting/errors.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/troubleshooting/errors.zh-cn.md @@ -8,93 +8,93 @@ description: > ## 无效选择器的异常 (Invalid Selector Exception) -某些时候难以获得正确的CSS以及XPath选择器. +某些时候难以获得正确的CSS以及XPath选择器。 ### 潜在原因 -您尝试使用的CSS或XPath选择器包含无效字符或无效查询. +您尝试使用的CSS或XPath选择器包含无效字符或无效查询。 ### 可行方案 -通过验证器服务运行选择器: +通过验证器服务运行选择器: * [CSS 验证器](http://csslint.net/) * [xPath 验证器](http://www.freeformatter.com/xpath-tester.html) -或者使用浏览器扩展程序来获取已知的良好值: +或者使用浏览器扩展程序来获取已知的良好值: * [SelectorsHub](https://selectorshub.com/selectorshub/) ## 没有这样元素的异常 (No Such Element Exception) -在您尝试找到该元素的当前时刻无法定位元素. +在您尝试找到该元素的当前时刻无法定位元素。 ### 潜在原因 -* 您在错误的位置寻找元素 (也许以前的操作不成功). +* 您在错误的位置寻找元素 (也许以前的操作不成功) * 您在错误的时间寻找元素 (该元素尚未显示在 DOM 中) * 自您编写代码以来定位器已变更 ### 可行方案 -* 确保您位于期望的页面上, 并且代码中的前置操作已正确完成 +* 确保您位于期望的页面上,并且代码中的前置操作已正确完成 * 确保您使用的是正确的 [等待策略]({{< ref "/documentation/webdriver/waits" >}}) * 使用浏览器的devtools控制台更新定位器或使用浏览器扩展程序,例如: * [SelectorsHub](https://selectorshub.com/selectorshub/) ## 过时元素引用的异常 (Stale Element Reference Exception) -元素先前的定位会过时, -导致当前无法访问. -元素不会自动重新定位; -驱动程序为元素创建引用ID, -并且有一个特定的位置,以期在 DOM 中找到. -如果在当前 DOM 中找不到元素, -任何使用该元素的操作都将导致此异常. +当成功定位到元素时, +WebDriver会为其设置一个引用ID作为标记, +如果由于上下文环境发生变化, +导致之前元素的位置发生了变化或者无法找到了, +WebDriver并不会自动重新定位, +任何使用之前元素所做的操作将报错该异常。 ### 常见因素 以下情况可能发生此异常: -* 您已刷新页面,或者页面的 DOM 已动态更改. -* 您已导航到其他页面. -* 您已切换到另一个窗口,或者进入/移出某个frame/iframe. +* 您已刷新页面,或者页面的 DOM 已动态更改。 +* 您已导航到其他页面。 +* 您已切换到另一个窗口,或者进入/移出某个 `frame` / `iframe`。 ### 常见方案 **DOM已变更** -当页面刷新或页面上的项目各处移动时, -页面上仍然有一个具有所需定位器的元素, -它只是不再被正在使用的元素对象访问, -并且必须重新定位该元素才能再次使用. -这往往通过以下两种方式之一完成: - -* 每次使用时, 始终重新定位元素. -虽然可能, 但元素在定位和使用元素之间的微秒内过时的可能性很小. -缺点是这并非最有效的方法, -特别是在远程网格上运行时. - -* 将 Web 元素与存储定位器的另一个对象包装在一起, -并缓存位于Selenium元素. -对此包装的对象执行操作时, -您可以尝试使用缓存的对象(若之前找到), -如果其已过时, 则异常可以捕获元素, -使用存储的定位器重新定位元素, 并重试该方法. -这更有效, 但如果您使用的定位器可能会导致问题, -在页面更改后引用不同的元素(而不是您想要的元素). +当页面刷新或页面上的项目各处移动时, +页面上仍然有一个具有所需定位器的元素, +它只是不再被正在使用的元素对象访问, +并且必须重新定位该元素才能再次使用。 + +这往往通过以下两种方式之一完成: + +* 每次使用时都要重新定位元素。 +尽管有可能元素在定位和使用元素之间的微秒内, +发生变化的可能性很小。 +缺点是这不是最有效的方法, +尤其是在 `Remote Grid`上运行时。 + +* 用另一个存储定位器的对象包装 Web 元素,并缓存定位的 Selenium 元素。 +对该包装对象执行操作时,您可以尝试使用之前找到的缓存对象, +如果它是发生了变化,则可以捕获异常, +使用存储的定位器重新定位元素,并重试该方法。 +这样效率更高,但如果您使用的定位器在页面更改后引用了不同的元素(而不是您想要的元素),则可能会导致问题。 **上下文已变更** -元素对象是为给定上下文存储的, -因此, 如果您移动到其他上下文 — -就像不同的窗口或不同的frame或iframe一样 — 元素引用将仍然有效, -但暂时无法访问. 在这种情况下, -它不会帮助重新定位元素, 因为它在当前上下文中不存在. -要解决此问题, 您需要确保在使用元素之前切换回正确的上下文. +元素对象是针对特定的上下文存储的, +因此如果您切换到不同的上下文, +比如不同的 `Window` 或不同的 `frame` 或 `iframe` 元素引用仍然有效, +但暂时无法访问。在这种情况下, +重新定位元素无济于事,因为它在当前上下文中不存在。 + +要解决此问题,您需要确保在使用该元素之前切换回正确的上下文。 **页面已变更** -这种情况是指您不仅更改了上下文, 还导航到了另一个页面, -并破坏了元素所在的上下文. -您不能只是将其从当前上下文中重新定位, -并且您无法切换回有效的活动上下文. -如果这是原因, 则对于您的错误, 您必须导航回正确的位置并重新定位它. +这种情况发生在您不仅更改了上下文, +而且导航到另一个页面并破坏了元素所在的上下文。 +您无法仅从当前上下文重新定位它, +也无法切换回元素有效的活动上下文。 +如果这是您的错误原因, +您必须回到正确的位置并重新定位元素。