这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

入门指南

如果你是Selenium的新手, 我们有一些资源帮助你快速入门.

Selenium 通过使用 WebDriver 支持市场上所有主流浏览器的自动化。 Webdriver 是一个 API 和协议,它定义了一个语言中立的接口,用于控制 web 浏览器的行为。 每个浏览器都有一个特定的 WebDriver 实现,称为驱动程序。 驱动程序是负责委派给浏览器的组件,并处理与 Selenium 和浏览器之间的通信。

这种分离是有意识地努力让浏览器供应商为其浏览器的实现负责的一部分。 Selenium 在可能的情况下使用这些第三方驱动程序, 但是在这些驱动程序不存在的情况下,它也提供了由项目自己维护的驱动程序。

Selenium 框架通过一个面向用户的界面将所有这些部分连接在一起, 该界面允许透明地使用不同的浏览器后端, 从而实现跨浏览器和跨平台自动化。

Selenium 设置与其他商业工具的设置完全不同。 要在自动化项目中使用 Selenium,您需要为您选择的语言安装语言绑定库。 此外,对于要自动运行并运行测试的浏览器,您将需要 WebDriver 二进制文件。

安装Selenium可分为三个步骤:

  1. 安装Selenium类库 为你最喜爱的编程语言
  2. 配置浏览器驱动 用以驱动你的浏览器 (例如GeckoDriver用于Firefox)
  3. (可选) 设置和配置 Selenium Grid 如果你想要扩展你的测试

如果您希望从低代码/录制和播放工具开始, 请检查 Selenium IDE

完成安装后,可以在你的文档 starting page 中运行. 然后前往 WebDriver 部分 了解更多关于 使用Selenium实现浏览器自动化的信息.

1 - 安装浏览器驱动

配置自动化的浏览器.

首先,您需要为自动化项目安装 Selenium 绑定库。 库的安装过程取决于您选择使用的语言。

可以使用 Maven 安装 Java 的 Selenium 库。 在项目 pom.xml 中添加 selenium-java 依赖项:

<dependency>
  <groupId>org.seleniumhq.selenium</groupId>
  <artifactId>selenium-java</artifactId>
  <version>4.X</version>
</dependency>

selenium-java 依赖项支持在所有 Selenium 支持的浏览器中运行自动化项目。 如果只想在特定的浏览器中运行测试,可以在 pom.xml 文件中添加该浏览器的依赖项。 例如,您应该在 pom.xml 文件中添加以下依赖项,以便于只在 Firefox 中运行测试:

<dependency>
  <groupId>org.seleniumhq.selenium</groupId>
  <artifactId>selenium-firefox-driver</artifactId>
  <version>4.X</version>
</dependency>

同样,如果您只想在 Chrome 上运行测试,您应该添加以下依赖项:

<dependency>
  <groupId>org.seleniumhq.selenium</groupId>
  <artifactId>selenium-chrome-driver</artifactId>
  <version>4.X</version>
</dependency>

可以使用 pip 安装 Python 的 Selenium 库:

pip install selenium

或者,您也可以下载 PyPI source archive (selenium-x.x.x.tar.gz) 并使用 setup.py 进行安装:

python setup.py install

可以使用 NuGet 安装 C# 的 Selenium 库:

# Using package manager
Install-Package Selenium.WebDriver
# or using .Net CLI
dotnet add package Selenium.WebDriver

支持的 .NET 版本

确保使用与.NET SDK版本兼容的相关Selenium包. 检查依赖的部分用以找出支持的 .NET 版本. 在本次升级时, .NET 5.0 (Visual Studio 2019) 是已知的被支持的版本, 并且 .NET 6.0 并未支持. 您可以下载 MSBuild Tools 2019 于此 以安装所需的组件和依赖项, 例如 .NET SDK 和 NuGet 包管理器.

使用 Visual Studio Code (vscode) 以及 C#

这是一个快速指南, 可帮助您开始使用 vscode 和 C#, 但可能需要进行更多调研. 按照上一节安装兼容的 .NET SDK. 还要安装适用于 C# 和 NuGet 的 vscode 扩展 (Ctrl-Shift-X). 参考 此处指令 创建并且使用C#运行 “Hello World” 的控制台项目. 您也可以使用命令行 dotnet new NUnit创建一个 NUnit 初创项目. 确保文件 %appdata%\NuGet\nuget.config 已正确配置, 因为某些开发人员报告说, 由于某些问题, 该文件将为空. 如果 nuget.config 为空, 或者未正确配置, 则Selenium项目的.NET构建将失败. 将以下部分添加到文件 nuget.config (如果为空) :

<configuration>
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
    <add key="nuget.org" value="https://www.nuget.org/api/v2/" />   
  </packageSources>
...

有关 nuget.config 的更多信息点此. 你也可以自定义 nuget.config 以满足所需.

现在, 返回 vscode, 按 Ctrl-Shift-P, 然后键入"NuGet Add Package", 然后输入所需的 Selenium 包, 如"Selenium.WebDriver".

按 Enter 并选择版本.

现在, 您可以通过vscode与文档中 C# 相关示例结合使用.

可以使用 gem 安装 Ruby 的 Selenium 库:

gem install selenium-webdriver

可以使用 npm 安装 JavaScript 的 Selenium 库

npm install selenium-webdriver
由于缺少Kotlin的原生语言的绑定, 您不得不借助Java的生态环境, 例如Maven Java

下一步

安装浏览器驱动

2 - 安装浏览器驱动

设置您的浏览器用于自动化.

通过WebDriver, Selenium支持市场上所有主要浏览器, 如Chrome、Firefox、Internet Explorer、Edge、Opera和Safari. WebDriver尽量使用浏览器内置的自动化支持 来驱动浏览器.

由于除Internet Explorer之外的所有驱动程序实现 都是由浏览器供应商自己提供的, 因此标准Selenium发行版中不包括这些驱动程序. 本节介绍了使用不同浏览器的基本要求.

在我们的驱动程序配置 文档中 阅读有关启动驱动程序的更多高级选项.

快速参考

浏览器支持的操作系统维护者下载问题追溯
Chromium/ChromeWindows/macOS/LinuxGoogle下载Issues
FirefoxWindows/macOS/LinuxMozilla下载Issues
EdgeWindows/macOSMicrosoft下载Issues
Internet ExplorerWindowsSelenium Project下载Issues
SafarimacOS High Sierra and newerApple内置Issues

注意: Opera驱动程序不支持w3c语法, 因此我们建议使用chromedriver来处理Opera. 请参见打开Opera浏览器的代码示例

使用驱动的三种方式

1. 驱动管理软件

大多数机器会自动更新浏览器, 但驱动程序不会. 为了确保为浏览器提供正确的驱动程序, 这里有许多第三方库可为您提供帮助.

  1. 导入 WebDriverManager
import io.github.bonigarcia.wdm.WebDriverManager;
  1. 调用 setup() 会自动将正确的浏览器驱动程序 放在代码可以看到的位置:
WebDriverManager.chromedriver().setup();
  1. 只需像平常一样初始化驱动程序:
ChromeDriver driver = new ChromeDriver();
  1. 导入 WebDriver Manager for Python
from webdriver_manager.chrome import ChromeDriverManager
  1. 使用 install() 获取管理器使用的位置, 并将其传递到服务类中
service = Service(executable_path=ChromeDriverManager().install())
  1. 使用 Service 实例并初始化驱动程序:
driver = webdriver.Chrome(service=service)
  1. 导入 WebDriver Manager Package
using WebDriverManager;
using WebDriverManager.DriverConfigs.Impl;
  1. 使用 SetUpDriver() 时需要一个配置类:
new DriverManager().SetUpDriver(new ChromeConfig());
  1. 像往常一样初始化驱动程序:
var driver = new ChromeDriver()
  1. 增加 webdrivers gem 到 Gemfile:
gem 'webdrivers', '~> 5.0'
  1. 在程序中Require webdrivers:
require 'webdrivers'
  1. 像往常一样初始化驱动程序:
driver = Selenium::WebDriver.for :chrome
There is not a recommended driver manager for JavaScript at this time
  1. 导入 WebDriver Manager
import io.github.bonigarcia.wdm.WebDriverManager;
  1. 在初始化驱动程序之前调用setup方法:
fun chrome(): WebDriver {
    WebDriverManager.chromedriver().setup()
    return ChromeDriver()
}

2. PATH 环境变量

此选项首先需要手动下载驱动程序 (有关链接, 请参阅快速参考 部分).

这是一个灵活的选项, 可以在不更新代码的情况下更改驱动程序的位置, 并且可以在多台机器上工作, 而不需要每台机器将驱动程序放在同一位置.

您可以将驱动程序放置在路径中已列出的目录中, 也可以将其放置在目录中并将其添加到PATH.

  • 要查看PATH上已有哪些目录, 请打开命令提示符/终端并键入:

要查看PATH上已经有哪些目录, 请打开Terminal并执行

echo $PATH

如果驱动程序的位置不在列出的目录中, 可以将新目录添加到PATH:

echo 'export PATH=$PATH:/path/to/driver' >> ~/.bash_profile
source ~/.bash_profile

您可以通过启动驱动程序来测试其是否被正确添加:

chromedriver

要查看PATH上已经有哪些目录, 请打开Terminal并执行:

echo $PATH

如果驱动程序的位置不在列出的目录中, 可以将新目录添加到PATH:

echo 'export PATH=$PATH:/path/to/driver' >> ~/.zshenv
source ~/.zshenv

您可以通过启动驱动程序来测试其是否被正确添加:

chromedriver

要查看PATH上已经有哪些目录, 请打开命令提示符并执行:

echo %PATH%

如果驱动程序的位置不在列出的目录中, 可以将新目录添加到PATH:

setx PATH "%PATH%;C:\WebDriver\bin"

您可以通过启动驱动程序来测试其是否被正确添加:

chromedriver.exe

如果PATH配置正确, 您将看到一些与驱动程序启动相关的输出:

Starting ChromeDriver 95.0.4638.54 (d31a821ec901f68d0d34ccdbaea45b4c86ce543e-refs/branch-heads/4638@{#871}) on port 9515
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.

想要重新控制命令提示符可以按下 Ctrl+C

3. 硬编码位置

与上面的选项2类似, 您需要手动下载驱动程序(有关链接, 请参阅快速参考 部分). 在代码中指定位置本身的优点是 不需要指出系统上的环境变量, 但缺点是使代码的灵活性大大降低.

System.setProperty("webdriver.chrome.driver","/path/to/chromedriver");
ChromeDriver driver = new ChromeDriver();
from selenium import webdriver
from selenium.webdriver.chrome.service import Service

service = Service(executable_path="/path/to/chromedriver")
driver = webdriver.Chrome(service=service)
var driver = new ChromeDriver(@"C:\WebDriver\bin");
service = Selenium::WebDriver::Service.chrome(path: '/path/to/chromedriver')
driver = Selenium::WebDriver.for :chrome, service: service
const {Builder} = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');

const service = new chrome.ServiceBuilder('/path/to/chromedriver');
const driver = new Builder().forBrowser('chrome').setChromeService(service).build();
import org.openqa.selenium.chrome.ChromeDriver

fun main(args: Array<String>) {
    System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver")
    val driver = ChromeDriver()
}

高级配置

有关如何更改驱动程序行为的更多信息, 请参见配置驱动程序参数 页面

下一步

打开和关闭浏览器

3 - 使用Selenium打开和关闭浏览器

使用每种浏览器启动和停止会话的代码示例.

当你已经完成 安装Selenium类库, 以及 浏览器所需的驱动, 您可以使用浏览器启动和停止会话.

通常, 浏览器都是根据特定的选项启动, 这些选项描述浏览器必须支持哪些功能, 以及浏览器在会话期间应如何运行. 有些功能由所有浏览器共享, 有些功能特定于所使用的浏览器. 此页面将显示使用默认功能启动浏览器的示例.

在学习如何开启一个会话后, 请查看下一段内容关于如何 编写第一个Selenium脚本的会话

Chrome

默认情况下, Selenium 4与Chrome v75及更高版本兼容. 请注意, Chrome浏览器和chromedriver的版本必须与主版本匹配.

除了共享功能外, 还可以使用特定的Chrome功能.

  ChromeOptions options = new ChromeOptions();
  driver = new ChromeDriver(options);
  
  driver.quit();
  
  options = ChromeOptions()
  driver = webdriver.Chrome(options=options)

  driver.quit()
  
  var options = new ChromeOptions();
  var driver = new ChromeDriver(options);

  driver.Quit();
  
  options = Selenium::WebDriver::Options.chrome
  driver = Selenium::WebDriver.for :chrome, options: options

  driver.quit
  
const {Builder} = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');

(async function openChromeTest() {
  try {
    let options = new chrome.Options();
    let driver = await new Builder()
                .setChromeOptions(options)
                .forBrowser('chrome')
                .build();
    await driver.get('https://www.google.com');
    await driver.quit();
  } catch (error) {
    console.log(error)
  }
})();
  val options = ChromeOptions()
  val driver = ChromeDriver(options)

  driver.quit()
  

Edge

微软Edge是用Chromium实现的, 是最早支持的v79版本. 与Chrome类似, edgedriver的主要版本号必须与Edge浏览器的主要版本匹配.

  EdgeOptions options = new EdgeOptions();
  driver = new EdgeDriver(options);

  driver.quit();
  
  options = EdgeOptions()
  driver = webdriver.Edge(options=options)

  driver.quit()
  
  var options = new EdgeOptions();
  var driver = new EdgeDriver(options);
  
  driver.Quit();
  
  options = Selenium::WebDriver::Options.edge
  driver = Selenium::WebDriver.for :edge, options: options

  driver.quit
  
const {Builder} = require('selenium-webdriver');
const edge = require('selenium-webdriver/edge');

(async function openEdgeTest() {
  try {
    let options = new edge.Options();
    let driver = await new Builder()
                .setChromeOptions(options)
                .forBrowser('edge')
                .build();
    await driver.get('https://www.google.com');
    await driver.quit();
  } catch (error) {
    console.log(error)
  }
})();
  val options = EdgeOptions()
  val driver = EdgeDriver(options)

  driver.quit()
  

Firefox

Selenium 4需要Firefox 78或更高版本. 建议始终使用geckodriver的最新版本.

  FirefoxOptions options = new FirefoxOptions();
  driver = new FirefoxDriver(options);

  driver.quit();
  
  options = FirefoxOptions()
  driver = webdriver.Firefox(options=options)

  driver.quit()
  
  var options = new FirefoxOptions();
  var driver = new FirefoxDriver(options);
  
  driver.Quit();
  
  options = Selenium::WebDriver::Options.firefox
  driver = Selenium::WebDriver.for :firefox, options: options

  driver.quit
  
const {Builder} = require('selenium-webdriver');
const firefox = require('selenium-webdriver/firefox');

(async function openFirefoxTest() {
  try {
    let options = new firefox.Options();
    let driver = await new Builder()
                .setChromeOptions(options)
                .forBrowser('firefox')
                .build();
    await driver.get('https://www.google.com');
    await driver.quit();
  } catch (error) {
    console.log(error)
  }
})();
  val options = FirefoxOptions()
  val driver = FirefoxDriver(options)

  driver.quit()
  

Internet Explorer

IE驱动程序是Selenium项目直接维护的唯一驱动程序. 虽然32位和64位版本的Internet Explorer都有可执行文件, 但64位驱动程序存在一些限制. 因此, 建议使用32位驱动程序.

Legacy

Selenium项目旨在支持微软认为最新的版本. 旧版本可能会工作, 但不受支持. 请注意, Internet Explorer 11将于2022年6月15日终止对包括Windows 10在内的某些操作系统的支持.

需要注意的是, 由于Internet Explorer首选项是针对登录用户的帐户保存的, 因此需要进行一些额外的设置.

有关使用Internet Explorer的更多信息, 请访问Selenium wiki

  InternetExplorerOptions options = new InternetExplorerOptions();
  driver = new InternetExplorerDriver(options);

  driver.quit();
  
  options = IEOptions()
  driver = webdriver.Ie(options=options)

  driver.quit()
  
  var options = new InternetExplorerOptions();
  var driver = new InternetExplorerDriver(options);
  
  driver.Quit();
  
  options = Selenium::WebDriver::Options.ie
  driver = Selenium::WebDriver.for :ie, options: options

  driver.quit
  
  const { Builder } = require("selenium-webdriver");
  const ie = require('selenium-webdriver/ie');

  let options = new ie.Options();
  let driver = await new Builder()
    .forBrowser('internetExplorer')
    .setIeOptions(options)
    .build();

  await driver.quit();
 
  val options = InternetExplorerOptions()
  val driver = InternetExplorerDriver(options)

  driver.quit()
  

兼容模式

可以使用IE驱动程序在IE兼容模式下使用微软Edge.

  InternetExplorerOptions options = new InternetExplorerOptions();
  options.attachToEdgeChrome();
  options.withEdgeExecutablePath("/path/to/edge/browser");
  
  driver = new InternetExplorerDriver(options);
  
  driver.quit();
  
  options = IEOptions()
  options.attach_to_edge_chrome = True
  options.edge_executable_path = "/path/to/edge/browser"
  driver = webdriver.Ie(options=options)

  driver.quit()
  
  var options = new InternetExplorerOptions
  {
    AttachToEdgeChrome = true,
    EdgeExecutablePath = "/path/to/edge/browser"
  };
  var driver = new InternetExplorerDriver(options);
  
  driver.Quit();
  
  options = Selenium::WebDriver::Options.ie
  options.attach_to_edge_chrome = true
  options.edge_executable_path = "/path/to/edge/browser"
  driver = Selenium::WebDriver.for :ie, options: options

  driver.quit
  
  let options = new ie.Options();
  options.setEdgeChromium(true);
  options.setEdgePath("/path/to/edge/browser);

  let driver = await new Builder()
    .forBrowser('internet explorer')
    .setIEOptions(options)
    .build();

  await driver.quit();
  
  val options = InternetExplorerOptions()
  options.attachToEdgeChrome()
  options.withEdgeExecutablePath("/path/to/edge/browser")
  val driver = InternetExplorerDriver(options)

  driver.quit()
  

Opera

由于opera驱动程序未设置w3c为默认语法, 但基于Chrome, 因此建议使用chromedriver驱动opera浏览器. 与所有Chromium实现一样, 确保浏览器版本与驱动程序版本匹配.

  //    Set webdriver.chrome.driver with Opera Driver
  System.setProperty("webdriver.chrome.driver", "OPERA_DRIVER_PATH");
  //    Create ChromeOptions Instance
  ChromeOptions chromeOptions = new ChromeOptions();
  //    Set W3C Dialect
  chromeOptions.setExperimentalOption("w3c", true);
  //    Create ChromeDriver Instance
  WebDriver driver = new ChromeDriver(chromeOptions);
  //    Open Target Website
  driver.get("https://www.selenium.dev");
  //    Quit
  driver.quit();
  
  options = ChromeOptions()
  options.binary_location = "path/to/opera/browser"
  driver = webdriver.Chrome(options=options)

  driver.quit()
  
  var options = new ChromeOptions
  {
    BinaryLocation = "/path/to/opera/browser"
  };
  var driver = new ChromeDriver(options);
  
  driver.Quit();
  
  options = Selenium::WebDriver::Options.chrome
  options.binary = '/path/to/opera/browser'
  driver = Selenium::WebDriver.for :chrome, options: options

  driver.quit
  
  const { Builder } = require("selenium-webdriver");
  const chrome = require('selenium-webdriver/chrome');

  let options = new chrome.Options();
  options.setChromeBinaryPath("/path/to/opera/browser");

  let driver = await new Builder()
    .forBrowser('chrome')
    .setChromeOptions(options)
    .build();

  await driver.quit();
  
  val options = ChromeOptions()
  options.setBinary("/path/to/opera/browser")
  val driver = ChromeDriver(options)
  
  driver.quit()
  

Safari

Desktop

与Chromium和Firefox驱动程序不同, safaridriver是随操作系统一起安装的. 要在Safari上启用自动化, 请从命令行运行以下命令:

safaridriver --enable
  SafariOptions options = new SafariOptions();
  driver = new SafariDriver(options);
  
  driver.quit();
  driver = webdriver.Safari()

  driver.quit()
  
  var options = new SafariOptions();
  var driver = new SafariDriver(options);

  driver.Quit();
  
  options = Selenium::WebDriver::Options.safari
  driver = Selenium::WebDriver.for :safari, options: options

  driver.quit
  
  const { Builder } = require("selenium-webdriver");
  const safari = require('selenium-webdriver/safari');

  let options = new safari.Options();
  let driver = await new Builder()
    .forBrowser('safari')
    .setSafariOptions(options)
    .build();

  await driver.quit();
  
  val options = SafariOptions()
  val driver = SafariDriver(options)

  driver.quit()
  

移动端

那些希望在iOS上实现Safari自动化的人 应该看看Appium项目.

下一步

创建你的第一个Selenium脚本

4 - 编写第一个Selenium脚本

逐步构建一个Selenium脚本的说明

当你完成 Selenium安装 and 驱动安装 后, 便可以开始书写Selenium脚本了.

八个基本组成部分

Selenium所做的一切, 就是发送给浏览器命令, 用以执行某些操作或为信息发送请求. 您将使用Selenium执行的大部分操作, 都是以下基本命令的组合:

1. 使用驱动实例开启会话

有关启动会话的更多详细信息, 请阅读我们关于打开和关闭浏览器的文档

        driver = new ChromeDriver();
    driver = webdriver.Chrome()
            var driver = new ChromeDriver();
    driver = Selenium::WebDriver.for :chrome
    let driver = await new Builder().forBrowser('chrome').build();
        driver = ChromeDriver()

2. 在浏览器上执行操作

在本例中, 我们 导航 到一个网页.

        driver.get("https://google.com");
    driver.get("https://google.com")
            driver.Navigate().GoToUrl("https://google.com");
    driver.get('https://google.com')
    await driver.get('https://www.google.com');
        driver.get("https://google.com")

3. 请求 浏览器信息

您可以请求一系列关于浏览器的信息 , 包括窗口句柄、浏览器尺寸/位置、cookie、警报等.

        String title = driver.getTitle();
    title = driver.title
            var title = driver.Title;
    title = driver.title
    await driver.getTitle();
        title = driver.title

4. 建立等待策略

将代码与浏览器的当前状态同步 是Selenium面临的最大挑战之一, 做好它是一个高级主题.

基本上, 您希望在尝试定位元素之前, 确保该元素位于页面上, 并且在尝试与该元素交互之前, 该元素处于可交互状态.

隐式等待很少是最好的解决方案, 但在这里最容易演示, 所以我们将使用它作为占位符.

阅读更多关于等待策略 的信息.

        driver.manage().timeouts().implicitlyWait(Duration.ofMillis(500));
    driver.implicitly_wait(0.5)
            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(500);
    driver.manage.timeouts.implicit_wait = 500
    await driver.manage().setTimeouts({implicit: 1000})
        driver.manage().timeouts().implicitlyWait(Duration.ofMillis(500))

5. 发送命令 查找元素

大多数Selenium会话中的主要命令都与元素相关, 如果不先找到元素, 就无法与之交互.

        WebElement searchBox = driver.findElement(By.name("q"));
        WebElement searchButton = driver.findElement(By.name("btnK"));
    search_box = driver.find_element(by=By.NAME, value="q")
    search_button = driver.find_element(by=By.NAME, value="btnK")
            var searchBox = driver.FindElement(By.Name("q"));
            var searchButton = driver.FindElement(By.Name("btnK"));
    search_box = driver.find_element(name: 'q')
    search_button = driver.find_element(name: 'btnK')
    let searchBox = await driver.findElement(By.name('q'));
    let searchButton = await driver.findElement(By.name('btnK'));
        var searchBox = driver.findElement(By.name("q"))
        val searchButton = driver.findElement(By.name("btnK"))

6. 操作元素

对于一个元素, 只有少数几个操作可以执行, 但您将经常使用它们.

        searchBox.sendKeys("Selenium");
        searchButton.click();
    search_box.send_keys("Selenium")
    search_button.click()
            searchBox.SendKeys("Selenium");
            searchButton.Click();
    search_box.send_keys('Selenium')
    search_button.click
    await searchBox.sendKeys('Selenium');
    await searchButton.click();
        searchBox.sendKeys("Selenium")
        searchButton.click()

7. 获取元素信息

元素存储了很多被请求的信息. 请注意, 我们需要重新定位搜索框, 因为自从我们第一次找到它以来, DOM已经发生了变化.

        String value = searchBox.getAttribute("value");
    value = search_box.get_attribute("value")
            var value = searchBox.GetAttribute("value");
    value = search_box.attribute('value')
    let value = await searchBox.getAttribute("value");
        val value = searchBox.getAttribute("value")

8. 结束会话

这将结束驱动程序进程, 默认情况下, 该进程也会关闭浏览器. 无法向此驱动程序实例发送更多命令.

        driver.quit();
    driver.quit()
            driver.Quit();
    await driver.quit();
        driver.quit()

组合所有事情

让我们将这8个部分组合成一个完整的脚本, 包括需要使用的库:

按照选项卡底部的链接查看代码示例, 因为它将使用测试运行程序而不是独立文件执行.

package dev.selenium.getting_started;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

import java.time.Duration;

public class FirstScriptTest {
    public WebDriver driver;

    @Test
    public void eightComponents() {
        driver = new ChromeDriver();

        driver.get("https://google.com");

        String title = driver.getTitle();
        Assertions.assertEquals("Google", title);

        driver.manage().timeouts().implicitlyWait(Duration.ofMillis(500));

        WebElement searchBox = driver.findElement(By.name("q"));
        WebElement searchButton = driver.findElement(By.name("btnK"));

        searchBox.sendKeys("Selenium");
        searchButton.click();

        searchBox = driver.findElement(By.name("q"));
        String value = searchBox.getAttribute("value");
        Assertions.assertEquals("Selenium", value);

        driver.quit();
    }
}
from selenium import webdriver
from selenium.webdriver.common.by import By


def test_eight_components():
    driver = webdriver.Chrome()

    driver.get("https://google.com")

    title = driver.title
    assert title == "Google"

    driver.implicitly_wait(0.5)

    search_box = driver.find_element(by=By.NAME, value="q")
    search_button = driver.find_element(by=By.NAME, value="btnK")

    search_box.send_keys("Selenium")
    search_button.click()

    search_box = driver.find_element(by=By.NAME, value="q")
    value = search_box.get_attribute("value")
    assert value == "Selenium"

    driver.quit()
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;

namespace SeleniumDocs.GettingStarted
{
    [TestClass]
    public class FirstScriptTest
    {

        [TestMethod]
        public void ChromeSession()
        {
            var driver = new ChromeDriver();

            driver.Navigate().GoToUrl("https://google.com");

            var title = driver.Title;
            Assert.AreEqual("Google", title);

            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(500);

            var searchBox = driver.FindElement(By.Name("q"));
            var searchButton = driver.FindElement(By.Name("btnK"));
            
            searchBox.SendKeys("Selenium");
            searchButton.Click();
            
            searchBox = driver.FindElement(By.Name("q"));
            var value = searchBox.GetAttribute("value");
            Assert.AreEqual("Selenium", value);

            driver.Quit();
        }
    }
}
# frozen_string_literal: true

RSpec.describe 'First Script' do
  it 'uses eight components' do
    driver = Selenium::WebDriver.for :chrome

    driver.get('https://google.com')

    title = driver.title
    expect(title).to eq('Google')

    driver.manage.timeouts.implicit_wait = 500

    search_box = driver.find_element(name: 'q')
    search_button = driver.find_element(name: 'btnK')

    search_box.send_keys('Selenium')
    search_button.click

    search_box = driver.find_element(name: 'q')
    value = search_box.attribute('value')
    expect(value).to eq('Selenium')

    driver.quit
  end
end
const {Builder, By} = require('selenium-webdriver');
const assert = require('assert');

(async function firstScript() {
  try {
    let driver = await new Builder().forBrowser('chrome').build();

    await driver.get('https://www.google.com');

    await driver.getTitle();

    await driver.manage().setTimeouts({implicit: 1000})

    let searchBox = await driver.findElement(By.name('q'));
    let searchButton = await driver.findElement(By.name('btnK'));

    await searchBox.sendKeys('Selenium');
    await searchButton.click();

    let value = await searchBox.getAttribute("value");
    assert.deepStrictEqual(value, "Selenium")

    await driver.quit();
  } catch (error) {
    console.log(error)
  }
})();
package dev.selenium.getting_started

import io.github.bonigarcia.wdm.WebDriverManager
import org.junit.jupiter.api.*
import org.junit.jupiter.api.Assertions.assertEquals
import org.openqa.selenium.By
import org.openqa.selenium.WebDriver
import org.openqa.selenium.chrome.ChromeDriver
import java.time.Duration

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class FirstScriptTest {
    private lateinit var driver: WebDriver

    @Test
    fun eightComponents() {
        driver = ChromeDriver()

        driver.get("https://google.com")

        title = driver.title
        assertEquals("Google", title)

        driver.manage().timeouts().implicitlyWait(Duration.ofMillis(500))

        var searchBox = driver.findElement(By.name("q"))
        val searchButton = driver.findElement(By.name("btnK"))

        searchBox.sendKeys("Selenium")
        searchButton.click()

        searchBox = driver.findElement(By.name("q"))
        val value = searchBox.getAttribute("value")
        assertEquals("Selenium", value)

        driver.quit()
    }
}

接下来的步骤

利用你所学的知识, 构建你的Selenium代码.

当您发现需要更多功能时, 请阅读我们的WebDriver文档的其余部分.

5 - 升级到Selenium 4

对Selenium 4感兴趣? 查看本指南, 它将帮助您升级到最新版本!

如果您使用的是官方支持的语言 (Ruby、JavaScript、C#、Python和Java), 那么升级到Selenium 4应该是一个轻松的过程. 在某些情况下可能会出现一些问题, 本指南将帮助您解决这些问题. 我们将完成升级项目依赖项的步骤, 并了解版本升级带来的主要反对意见和更改.

请按照以下步骤升级到Selenium 4:

  • 准备我们的测试代码
  • 升级依赖
  • 潜在错误和弃用消息

注意:在开发Selenium 3.x版本的同时, 实现了对W3C WebDriver标准的支持. 此新协议和遗留JSON Wire协议均受支持. 在3.11版前后, Selenium代码与W3C 1级规范兼容. 最新版本的Selenium 3中的W3C兼容代码将在Selenium 4中正常工作.

准备测试代码

Selenium 4 移除了对遗留协议的支持, 并在底层实现上默认使用 W3C WebDriver 标准.
对于大多数情况, 这种实现不会影响终端用户.
主要的例外是 CapabilitiesActions 类.

Capabilities

如果测试capabilities的结构不符合 W3C标准, 可能会导致会话无法正常开启.
以下是 W3C WebDriver 标准capabilities列表:

  • browserName
  • browserVersion (替代 version)
  • platformName (替代 platform)
  • acceptInsecureCerts
  • pageLoadStrategy
  • proxy
  • timeouts
  • unhandledPromptBehavior

可以在以下位置找到标准capabilities的最新列表 W3C WebDriver.

上面列表中未包含的任何capability, 都需要包含供应商前缀. 这适用于浏览器特定capability 以及云供应商特定capability. 例如, 如果您的云供应商为您的测试 使用 buildname capability, 您需要将它们包装在一个 cloud: options 块中 (请与您的云供应商联系以获取适当的前缀).

Before

DesiredCapabilities caps = DesiredCapabilities.firefox();
caps.setCapability("platform", "Windows 10");
caps.setCapability("version", "92");
caps.setCapability("build", myTestBuild);
caps.setCapability("name", myTestName);
WebDriver driver = new RemoteWebDriver(new URL(cloudUrl), caps);
caps = {};
caps['browserName'] = 'Firefox';
caps['platform'] = 'Windows 10';
caps['version'] = '92';
caps['build'] = myTestBuild;
caps['name'] = myTestName;
DesiredCapabilities caps = new DesiredCapabilities();
caps.SetCapability("browserName", "firefox");
caps.SetCapability("platform", "Windows 10");
caps.SetCapability("version", "92");
caps.SetCapability("build", myTestBuild);
caps.SetCapability("name", myTestName);
var driver = new RemoteWebDriver(new Uri(CloudURL), caps);
caps = Selenium: : WebDriver: : Remote: : Capabilities.firefox
caps[: platform] = 'Windows 10'
caps[: version] = '92'
caps[: build] = my_test_build
caps[: name] = my_test_name
driver = Selenium: : WebDriver.for : remote, url:  cloud_url, desired_capabilities:  caps
caps = {}
caps['browserName'] = 'firefox'
caps['platform'] = 'Windows 10'
caps['version'] = '92'
caps['build'] = my_test_build
caps['name'] = my_test_name
driver = webdriver.Remote(cloud_url, desired_capabilities=caps)

After

FirefoxOptions browserOptions = new FirefoxOptions();
browserOptions.setPlatformName("Windows 10");
browserOptions.setBrowserVersion("92");
Map<String, Object> cloudOptions = new HashMap<>();
cloudOptions.put("build", myTestBuild);
cloudOptions.put("name", myTestName);
browserOptions.setCapability("cloud: options", cloudOptions);
WebDriver driver = new RemoteWebDriver(new URL(cloudUrl), browserOptions);
capabilities = {
  browserName:  'firefox',
  browserVersion:  '92',
  platformName:  'Windows 10',
  'cloud: options':  {
     build:  myTestBuild,
     name:  myTestName,
  }
}
var browserOptions = new FirefoxOptions();
browserOptions.PlatformName = "Windows 10";
browserOptions.BrowserVersion = "92";
var cloudOptions = new Dictionary<string, object>();
cloudOptions.Add("build", myTestBuild);
cloudOptions.Add("name", myTestName);
browserOptions.AddAdditionalOption("cloud: options", cloudOptions);
var driver = new RemoteWebDriver(new Uri(CloudURL), browserOptions);
options = Selenium: : WebDriver: : Options.firefox
options.browser_version = 'latest'
options.platform_name = 'Windows 10'
cloud_options = {}
cloud_options[: build] = my_test_build
cloud_options[: name] = my_test_name
options.add_option('cloud: options', cloud_options)
driver = Selenium: : WebDriver.for : remote, url:  cloud_url, capabilities:  options
from selenium.webdriver.firefox.options import Options as FirefoxOptions
options = FirefoxOptions()
options.browser_version = '92'
options.platform_name = 'Windows 10'
cloud_options = {}
cloud_options['build'] = my_test_build
cloud_options['name'] = my_test_name
options.set_capability('cloud: options', cloud_options)
driver = webdriver.Remote(cloud_url, options=options)

在 Java 中查找元素工具方法

在 Java 绑定(FindsBy 接口)中 查找元素的工具方法已被删除 因为它们仅供内部使用.
以下代码示例更好地解释了这一点.

使用 findElement* 查找单个元素

Before

driver.findElementByClassName("className");
driver.findElementByCssSelector(".className");
driver.findElementById("elementId");
driver.findElementByLinkText("linkText");
driver.findElementByName("elementName");
driver.findElementByPartialLinkText("partialText");
driver.findElementByTagName("elementTagName");
driver.findElementByXPath("xPath");

After

driver.findElement(By.className("className"));
driver.findElement(By.cssSelector(".className"));
driver.findElement(By.id("elementId"));
driver.findElement(By.linkText("linkText"));
driver.findElement(By.name("elementName"));
driver.findElement(By.partialLinkText("partialText"));
driver.findElement(By.tagName("elementTagName"));
driver.findElement(By.xpath("xPath"));

使用 findElements* 查找多个元素

Before

driver.findElementsByClassName("className");
driver.findElementsByCssSelector(".className");
driver.findElementsById("elementId");
driver.findElementsByLinkText("linkText");
driver.findElementsByName("elementName");
driver.findElementsByPartialLinkText("partialText");
driver.findElementsByTagName("elementTagName");
driver.findElementsByXPath("xPath");

After

driver.findElements(By.className("className"));
driver.findElements(By.cssSelector(".className"));
driver.findElements(By.id("elementId"));
driver.findElements(By.linkText("linkText"));
driver.findElements(By.name("elementName"));
driver.findElements(By.partialLinkText("partialText"));
driver.findElements(By.tagName("elementTagName"));
driver.findElements(By.xpath("xPath"));

升级依赖

检查下面的小节以安装 Selenium 4 并升级您的项目依赖项.

Java

升级 Selenium 的过程取决于所使用的构建工具.
我们将涵盖Java 中最常见的 MavenGradle .
所需的最低 Java 版本仍然是 8.

Maven

Before

<dependencies>
  <!-- more dependencies ... -->
  <dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.141.59</version>
  </dependency>
  <!-- more dependencies ... -->
</dependencies>

After

<dependencies>
    <!-- more dependencies ... -->
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.0.0</version>
    </dependency>
    <!-- more dependencies ... -->
</dependencies>

进行更改后, 您可以在pom.xml 文件的同一目录中 执行 mvn clean compile .

Gradle

Before

plugins {
    id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
    mavenCentral()
}
dependencies {
    testImplementation 'org.junit.jupiter: junit-jupiter-api: 5.7.0'
    testRuntimeOnly 'org.junit.jupiter: junit-jupiter-engine: 5.7.0'
    implementation group:  'org.seleniumhq.selenium', name:  'selenium-java', version:  '3.141.59'
}
test {
    useJUnitPlatform()
}

After

plugins {
    id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
    mavenCentral()
}
dependencies {
    testImplementation 'org.junit.jupiter: junit-jupiter-api: 5.7.0'
    testRuntimeOnly 'org.junit.jupiter: junit-jupiter-engine: 5.7.0'
    implementation group:  'org.seleniumhq.selenium', name:  'selenium-java', version:  '4.0.0'
}
test {
    useJUnitPlatform()
}

进行更改后, 您可以在 build.gradle 文件所在的同一目录中 执行./gradlew clean build .

要检查所有 Java 版本, 您可以前往 MVNRepository .

C#

在 C# 中获取 Selenium 4 更新的 地方是 NuGet .
在下面包 Selenium.WebDriver 你可以获得更新到最新版本的说明.
在 Visual Studio 内部, 您可以通过 NuGet 包管理器执行:

PM> Install-Package Selenium.WebDriver -Version 4.0.0

Python

使用 Python 的最重要变化是所需的最低版本. Selenium 4 将至少需要 Python 3.7 或更高版本.
更多详细信息可以在 Python 包索引 .
基于命令行做升级的话, 你可以执行:

pip install selenium==4.0.0

Ruby

Selenium 4 的更新细节 可以在RubyGems中的gem发现 selenium-webdriver .
要安装最新版本, 您可以执行:

gem install selenium-webdriver

将以下内容添加到你的Gemfile:

gem 'selenium-webdriver', '~> 4.0.0'

JavaScript

可以在 Node 包管理器中找到 selenium-webdriver 包, npmjs .
Selenium 4 可以在 这里 找到.
要安装, 你可以执行:

npm install selenium-webdriver

或者, 更新你的 package.json 并运行 npm install :

{
  "name":  "selenium-tests",
  "version":  "1.0.0",
  "dependencies":  {
    "selenium-webdriver":  "^4.0.0"
  }
}

潜在错误和弃用消息

这是一组代码示例, 它们将有助于克服 您升级到 Selenium 4 后 可能会遇到的弃用消息.

Java

等待和超时

Timeout 中接收到的参数 已经从期望 (long time, TimeUnit unit) 切换到期待 (Duration duration) .

Before

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.manage().timeouts().setScriptTimeout(2, TimeUnit.MINUTES);
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);

After

driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
driver.manage().timeouts().scriptTimeout(Duration.ofMinutes(2));
driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(10));

等待现在也期望不同的参数. WebDriverWait 现在期待一个 Duration 而不是以秒和毫秒为单位的 long 超时. FluentWait 的工具方法 withTimeoutpollingEvery 已经从期望 (long time, TimeUnit unit) 切换到 期待(Duration duration) .

Before

new WebDriverWait(driver, 3)
.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#id")));

Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
  .withTimeout(30, TimeUnit.SECONDS)
  .pollingEvery(5, TimeUnit.SECONDS)
  .ignoring(NoSuchElementException.class);

After

new WebDriverWait(driver, Duration.ofSeconds(3))
  .until(ExpectedConditions.elementToBeClickable(By.cssSelector("#id")));

  Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
  .withTimeout(Duration.ofSeconds(30))
  .pollingEvery(Duration.ofSeconds(5))
  .ignoring(NoSuchElementException.class);

合并capabilities不再改变调用对象

曾经可以将一组不同的capabilities合并到另一组中, 并且改变调用对象.
现在, 需要分配合并操作的结果.

Before

MutableCapabilities capabilities = new MutableCapabilities();
capabilities.setCapability("platformVersion", "Windows 10");
FirefoxOptions options = new FirefoxOptions();
options.setHeadless(true);
options.merge(capabilities);

作为结果, options 对象被修改

After

MutableCapabilities capabilities = new MutableCapabilities();
capabilities.setCapability("platformVersion", "Windows 10");
FirefoxOptions options = new FirefoxOptions();
options.setHeadless(true);
options = options.merge(capabilities);

merge 调用的结果需要分配给一个对象.

Firefox 遗留模式

在 GeckoDriver 出现之前, Selenium 项目有一个驱动程序实现来自动化 Firefox(版本 <48).
但是, 不再需要此实现, 因为在最新版本的 Firefox 中它不起作用.
为避免升级到 Selenium 4 时出现重大问题, setLegacy选项将显示为已弃用.
建议停止使用旧的实现 并且只依赖 GeckoDriver.
以下代码将显示在升级之后弃用的 setLegacy 行.

FirefoxOptions options = new FirefoxOptions();
options.setLegacy(true);

BrowserType

BrowserType 接口已经存在很长时间了, 但是其已变为弃用 且推荐使用新的 Browser 接口.

Before

MutableCapabilities capabilities = new MutableCapabilities();
capabilities.setCapability("browserVersion", "92");
capabilities.setCapability("browserName", BrowserType.FIREFOX);

After

MutableCapabilities capabilities = new MutableCapabilities();
capabilities.setCapability("browserVersion", "92");
capabilities.setCapability("browserName", Browser.FIREFOX);

C#

AddAdditionalCapability 已弃用

推荐使用AddAdditionalOption替代.
以下为一个示例:

Before

var browserOptions = new ChromeOptions();
browserOptions.PlatformName = "Windows 10";
browserOptions.BrowserVersion = "latest";
var cloudOptions = new Dictionary<string, object>();
browserOptions.AddAdditionalCapability("cloud: options", cloudOptions, true);

After

var browserOptions = new ChromeOptions();
browserOptions.PlatformName = "Windows 10";
browserOptions.BrowserVersion = "latest";
var cloudOptions = new Dictionary<string, object>();
browserOptions.AddAdditionalOption("cloud: options", cloudOptions);

Python

executable_path 已弃用, 请传递一个服务对象

在Selenium 4中,
您需要从服务对象设置驱动程序的 可执行路径 , 以防止出现弃用警告. (或者不要设置路径, 而是确保所需的驱动程序位于系统路径上.)

Before

from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option("useAutomationExtension", False)
driver = webdriver.Chrome(executable_path=CHROMEDRIVER_PATH, options=options)

After

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
options = webdriver.ChromeOptions()
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option("useAutomationExtension", False)
service = ChromeService(executable_path=CHROMEDRIVER_PATH)
driver = webdriver.Chrome(service=service, options=options)

总结

我们已经过了升级到 Selenium 4 时要考虑的主要变化. 涵盖为升级准备测试代码时要涵盖的不同方面, 包括关于如何避免 使用Selenium新版本时 可能出现的潜在问题的建议.
最后, 我们还介绍了一系列您可能会遇到的升级问题, 分享这些问题的潜在修复方案.

本文最初发布于 https://saucelabs.com/resources/articles/how-to-upgrade-to-selenium-4