Selenium 是一个涵盖各种工具和库的综合项目,用于实现 Web 浏览器自动化。Selenium 特别为 W3C WebDriver 规范 提供了基础架构,该规范是一个与平台和语言无关的编码接口,兼容所有主流 Web 浏览器。
该项目的实现离不开志愿者贡献者,他们慷慨地投入了数千小时的代码开发和维护。
本 README 适用于有意为该项目做出贡献的开发者。如果您希望开始使用 Selenium,请查看我们的 用户手册,获取详细的示例和说明;如果您遇到问题,可以通过多种方式 获取帮助。
创建您自己的本地开发环境以贡献 Selenium 所需的条件如下。
.bazelversion
文件中指定的 Bazel 版本,并将所有JAVA_HOME
环境变量设置为 Java 可执行文件的位置(JDK 而不是 JRE)javac
。如果您只安装了 JRE,则此命令将不存在。xcode-select --install
安装最新版本。build --host_platform=//:rosetta
添加到 .bazelrc.local
文件。我们正在努力几年前,Jim Evans 发表了一篇很棒的文章,主题是为 Selenium .NET 语言绑定设置 Windows 开发环境;这篇文章虽然已经过时,但其中包含了更详细的描述和截图,可能会对一些人有所帮助。
如果您想为项目做出贡献,但又不想搭建自己的本地开发环境,有两种替代方案可供选择。
GitPod 无需您自行创建本地开发环境,而是提供了一个现成的开发环境。
您也可以构建一个开发容器,它本质上是一个 Docker 容器,适用于使用 .devcontainer 目录中的 devcontainer.json 文件构建和测试 Selenium。VS Code 或 IntelliJ IDEA 等支持 IDE 应该会指导您如何创建这样的容器。
您还可以使用 dev image 目录中的 Dockerfile 构建一个适用于构建和测试 Selenium 的 Docker 镜像。
Selenium 使用名为 Bazel 的通用构建工具进行构建,以便我们能够轻松管理依赖项下载、生成所需的二进制文件、构建和发布软件包以及执行测试;所有这些都以快速、高效的方式进行。有关更详细的讨论,请阅读 Simon Stewart关于构建 Selenium 的文章。
我们经常使用自定义的 Rake 包装器来包装 Bazel 命令。这些命令通过 ./go
命令运行。
常用的 Bazel 命令有:
bazel build
— 评估依赖项、编译源文件并为指定目标生成输出文件。bazel run
— 构建目标并执行。bazel test
— 在上下文中构建并运行目标,并提供附加测试功能。bazel query
— 识别指定路径的可用目标。每个可构建的模块都定义在 BUILD.bazel
文件中。要执行模块,您需要以//
开头引用它,然后包含定义它的文件的相对路径,接着是 :
,最后是目标的名称。
例如,构建网格的目标名为“executable-grid”,它
在“selenium/java/src/org/openqa/selenium/grid/BAZEL.build”文件中定义。
因此,要构建网格,您需要运行:bazel build //java/src/org/openqa/selenium/grid:executable-grid
。
Bazel 文档提供了一个便捷指南,其中包含各种快捷方式以及构建多个目标的所有方法,Selenium 经常使用这些方法。
要为给定语言构建所有内容:
bazel build //<language>/...
如果仅构建网格,可以使用别名(日志将显示输出 jar 所在的位置):
bazel build grid
为了更简单,可以使用此 ./go
命令构建每个绑定:
./go <language>:build
团队中的大多数人使用 IntelliJ 进行日常编辑。如果您正在使用 IntelliJ,我们强烈建议您安装 Bazel IJ插件,其文档位于其官方网站。
要将 Selenium 与 IntelliJ Bazel 插件配合使用,请将代码库导入为 Bazel 项目,然后从 scripts 目录中选择项目视图文件。Mac/Linux 系统使用 ij.bazelproject
,Windows 系统使用 ij-win.bazelproject
。
我们也使用 Google Java Format 进行 Linting,因此使用 Google Java Formatter 插件会很有用;要使其正常工作,需要几个步骤,因此请阅读其配置文档。还有一个可以运行的自动格式化脚本:./scripts/format.sh
虽然 Selenium 不是使用 Maven 构建的,但您可以构建并安装 Selenium 组件
供 Maven 使用,方法是将其部署到本地 Maven 仓库 (~/.m2/repository
),使用以下命令:
./go java:install
依赖项在文件 MODULE.bazel 中定义。
要更新依赖项,请修改 MODULE.bazel
文件中的版本,然后运行:
RULES_JVM_EXTERNAL_REPIN=1 bazel run @maven//:pin
要自动更新并固定新的依赖项,请运行:
./go java:update
我们遵循 PEP8 Python 代码风格指南(除了我们使用 120 个字符的行长)。我们使用 linting/formatting 工具 ruff 进行检查和强制执行。此外,还有一个可以运行的自动格式化脚本:./scripts/format.sh
要在本地运行 Python 代码而不构建/安装包,您必须首先安装依赖项:
pip install -r py/requirements.txt
然后,构建生成的文件并将其复制到本地源代码树中:
./go py:local_dev
之后,您可以直接从源代码中的 py
目录导入 selenium 包。除了从源代码运行,您还可以在本地构建并安装 Selenium 包 (wheel):
./go py:install
这将尝试安装到全局 Python site-packages
目录中,该目录可能不可写。为避免这种情况,您应该在安装之前创建并激活一个虚拟环境。
除了使用 irb
,您还可以使用 bazel run //rb:console
命令创建一个加载了所有 gem 的交互式 REPL。如果您想调试代码,可以使用 debug
gem 进行调试:
binding.break
。ruby_debug
配置运行测试:bazel test --config ruby_debug <test>
。bazel-selenium/external/bundle/bin/rdbg -A
如果您想使用 RubyMine 进行开发,您可以使用 Bazel 工件进行配置:
rb/
作为主项目目录。bundle exec rake update
来创建最新的工件。如果此命令无效,请从 selenium
(父目录)运行 ./go rb:update
。../bazel-selenium/external/rules_ruby_dist/dist/bin/ruby
。要使 Carbo.Bazel.lock
与 Cargo.lock
保持同步,请运行:
CARGO_BAZEL_REPIN=true bazel sync --only=crates
Bazel 有许多专门用于测试的配置。
以下是我们在测试 Selenium 代码时使用的参数示例:
--pin_browsers
- 运行构建中定义的特定浏览器版本(版本会定期更新)--headless
- 以无头模式运行浏览器(Chrome、Edge 和 Firefox 支持)--flaky_test_attempts 3
- 最多重新运行 3 次失败的测试--local_test_jobs 1
- 控制测试的并行度--cache_test_results=no
, -t-
- 禁用测试结果缓存并重新运行所有测试--test_output all
- 打印测试的所有输出,而不仅仅是错误--test_output streamed
- 逐个运行所有测试并立即打印其输出--test_env FOO=bar
- 将额外的环境变量传递给测试进程--run_under="xvfb-run" -a"
- 执行前插入的前缀Selenium 测试可以按大小进行过滤:
可以使用 test_size_filters
参数进行过滤,如下所示:
bazel test //<language>/... --test_size_filters=small
测试也可以按标签进行过滤,如下所示:
bazel test //<language>/... --test_tag_filters=this,-not-this
如果有多个 --test_tag_filters
,则只考虑最后一个,因此,如果还使用继承的配置,请谨慎使用。
运行单元测试:
bazel test //java/... --test_size_filters=small
运行集成测试:
bazel test //java/... --test_size_filters=medium
运行浏览器测试:
bazel test //java/... --test_size_filters=large --test_tag_filters=<browser>
运行特定测试:
bazel test //java/test/org/openqa/selenium/chrome:ChromeDriverFunctionalTest
要运行测试,请运行:
bazel test //javascript/selenium-webdriver:all
您可以使用 --test_env
将浏览器名称设置为 SELENIUM_BROWSER
。
bazel test //javascript/selenium-webdriver:all --test_env=SELENIUM_BROWSER=firefox
使用以下命令运行单元测试:
bazel test //py:unit
使用特定浏览器运行常见测试:
bazel test //py:common-<browsername>
使用特定浏览器运行常见测试(包括 BiDi 测试):
bazel test //py:common-<browsername>-bidi
使用特定浏览器运行测试:
bazel test //py:test-<browsername>
运行所有 Python 测试:
bazel test //py:all
Rust 测试使用以下命令行运行:
bazel test //rust/...
默认情况下,Bazel 会在您当前的 X-server 界面中运行这些测试。如果您愿意,
也可以在虚拟或嵌套的 X-server 中运行它们。
Xvfb :99
或 Xnest :99
DISPLAY=:99 jwm
bazel test --test_env=DISPLAY=:99 //java/... --test_tag_filters=chrome
在虚拟 X 服务器中运行测试的一种简单方法是使用 Bazel 的 --run_under
功能:
bazel test --run_under="xvfb-run -a" //java/...
API 文档可在此处找到:
更新特定语言的 API 文档:./go <language>:docs
更新所有文档:./go all:docs
发布是构建和发布的结合,通常需要协调多个执行,以及额外的处理。正如构建 部分所述,我们使用 Rake 任务和 ./go
命令来完成这些操作。这些 ./go
命令包含 --stamp
参数,用于提供有关已构建资产的必要信息。
您可以使用以下命令构建和发布所有内容:
./go all:release
要构建和发布特定语言的资源:
./go <language>:release
如果您有权访问 Selenium EngFlow 代码库,您可以使用以下命令远程构建资产并将其下载到本地:
./go all:release['--config', 'release']