WebDriver 以本地化方式驱动浏览器,就像用户在本地或使用 Selenium 服务器的远程机器上所做的那样,这标志着浏览器自动化的飞跃。
Selenium WebDriver 指的是语言绑定和各个浏览器控制代码的实现。 这通常被称为 WebDriver。
Selenium WebDriver 是 W3C 推荐标准
WebDriver 被设计成一个简单和简洁的编程接口。
WebDriver 是一个简洁的面向对象 API。
它能有效地驱动浏览器。
WebDriver 以本地化方式驱动浏览器,就像用户在本地或使用 Selenium 服务器的远程机器上所做的那样,这标志着浏览器自动化的飞跃。
Selenium WebDriver 指的是语言绑定和各个浏览器控制代码的实现。 这通常被称为 WebDriver。
Selenium WebDriver 是 W3C 推荐标准
WebDriver 被设计成一个简单和简洁的编程接口。
WebDriver 是一个简洁的面向对象 API。
它能有效地驱动浏览器。
Selenium 通过使用 WebDriver 支持市场上所有主流浏览器的自动化。 Webdriver 是一个 API 和协议,它定义了一个语言中立的接口,用于控制 web 浏览器的行为。 每个浏览器都有一个特定的 WebDriver 实现,称为驱动程序。 驱动程序是负责委派给浏览器的组件,并处理与 Selenium 和浏览器之间的通信。
这种分离是有意识地努力让浏览器供应商为其浏览器的实现负责的一部分。 Selenium 在可能的情况下使用这些第三方驱动程序, 但是在这些驱动程序不存在的情况下,它也提供了由项目自己维护的驱动程序。
Selenium 框架通过一个面向用户的界面将所有这些部分连接在一起, 该界面允许透明地使用不同的浏览器后端, 从而实现跨浏览器和跨平台自动化。
Selenium setup is quite different from the setup of other commercial tools. Before you can start writing Selenium code, you have to install the language bindings libraries for your language of choice, the browser you want to use, and the driver for that browser.
Follow the links below to get up and going with Selenium WebDriver.
If you wish to start with a low-code/record and playback tool, please check Selenium IDE
Once you get things working, if you want to scale up your tests, check out the Selenium Grid.
首先,您需要为自动化项目安装 Selenium 绑定库。 库的安装过程取决于您选择使用的语言。
查看该库所支持java的最低版本 here.
应熟练掌握build tool以安装支持java的Selenium库
具体的依赖位于项目中的 pom.xml
文件:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.12.1</version>
</dependency>
具体的依赖位于项目中的 build.gradle
文件中的 testImplementation
:
testImplementation 'org.seleniumhq.selenium:selenium-java:4.12.1'
该库所支持的Python版本最低版本可以在
支持的Python版本
章节中找到 PyPi
这里提供了几种不同的方式来安装 Selenium .
pip install selenium
此外你可以从这里下载 PyPI source archive (selenium-x.x.x.tar.gz) 并通过: setup.py 文件安装:
python setup.py install
为了在项目中使用它,需要将它添加到 requirements.txt
文件中:
selenium==4.12.0
Selenium 所支持的所有平台的列表一览 见诸于 Nuget
该处阐述了一些安装Selenium的选项.
Install-Package Selenium.WebDriver
dotnet add package Selenium.WebDriver
在 csproj
文件里, 具体的依赖 PackageReference
(包参数) 位于 ItemGroup
(项目组)中:
<PackageReference Include="Selenium.WebDriver" Version="4.12.4" />
更多的注意事项,适用于使用 Visual Studio Code (vscode) 和 C#
安装兼容的 .NET SDK 作为章节的先决条件
同时安装 vscode 的扩展 (Ctrl-Shift-X)以适配 C# 和 NuGet
可以遵照此处进行 操作指南
创建 C# 控制台项目并运行 “Hello World”.
你也可以用命令行 dotnet new NUnit
创建NUnit初阶项目.
确保文件 %appdata%\NuGet\nuget.config
已经配置完成,就像某位开发者报告的问题一样,它可能因为某种因素被自动清空.
如果 nuget.config
是空的,或者未配置的,那么 .NET 创建的Selenium项目可能失败.
加入如下章节到文件 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
.
按下回车并选择版本.
现在你可以使用说明文档中关于 C# vscode下的案例了.
你可以查看 Selenium 对 Ruby 版本支持和最低支持. 具体位于 rubygems.org
Selenium 可以使用两种不同方法安装.
gem install selenium-webdriver
gem 'selenium-devtools', '~> 0.116'
You can find the minimum required version of Node for any given version of Selenium in the
你可以在此查看 Selenium 对 Node 的版本支持情况
位于 Node Support Policy
中的相关章节 npmjs
Selenium is typically installed using npm.
npm install selenium-webdriver
在你的项目 package.json
, 必须加入到 dependencies
:
"mocha": "^10.2.0"
当你完成 Selenium安装 后, 便可以开始书写Selenium脚本了.
Note: if you get an error about drivers not found, please read about troubleshooting the driver location error
Selenium所做的一切, 就是发送给浏览器命令, 用以执行某些操作或为信息发送请求. 您将使用Selenium执行的大部分操作, 都是以下基本命令的组合:
关于如何启动会话,请浏览我们的文档 驱动会话
WebDriver driver = new ChromeDriver();
driver = webdriver.Chrome()
IWebDriver driver = new ChromeDriver();
driver = Selenium::WebDriver.for :chrome
driver = await new Builder().forBrowser('chrome').build();
driver = ChromeDriver()
在本例中, 我们 导航 到一个网页.
driver.get("https://www.selenium.dev/selenium/web/web-form.html");
driver.get("https://www.selenium.dev/selenium/web/web-form.html")
driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/web-form.html");
driver.get('https://www.selenium.dev/selenium/web/web-form.html')
await driver.get('https://www.selenium.dev/selenium/web/web-form.html');
driver.get("https://www.selenium.dev/selenium/web/web-form.html")
您可以请求一系列关于浏览器的信息 , 包括窗口句柄、浏览器尺寸/位置、cookie、警报等.
String title = driver.getTitle();
title = driver.title
var title = driver.Title;
title = driver.title
let title = await driver.getTitle();
val title = driver.title
将代码与浏览器的当前状态同步 是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: 500});
driver.manage().timeouts().implicitlyWait(Duration.ofMillis(500))
大多数Selenium会话中的主要命令都与元素相关, 如果不先找到元素, 就无法与之交互.
WebElement textBox = driver.findElement(By.name("my-text"));
WebElement submitButton = driver.findElement(By.cssSelector("button"));
text_box = driver.find_element(by=By.NAME, value="my-text")
submit_button = driver.find_element(by=By.CSS_SELECTOR, value="button")
var textBox = driver.FindElement(By.Name("my-text"));
var submitButton = driver.FindElement(By.TagName("button"));
text_box = driver.find_element(name: 'my-text')
submit_button = driver.find_element(tag_name: 'button')
let textBox = await driver.findElement(By.name('my-text'));
let submitButton = await driver.findElement(By.css('button'));
var textBox = driver.findElement(By.name("my-text"))
val submitButton = driver.findElement(By.cssSelector("button"))
对于一个元素, 只有少数几个操作可以执行, 但您将经常使用它们.
textBox.sendKeys("Selenium");
submitButton.click();
text_box.send_keys("Selenium")
submit_button.click()
textBox.SendKeys("Selenium");
submitButton.Click();
text_box.send_keys('Selenium')
submit_button.click
await textBox.sendKeys('Selenium');
await submitButton.click();
textBox.sendKeys("Selenium")
submitButton.click()
元素存储了很多被请求的信息.
String value = message.getText();
value = message.text
var value = message.Text;
value = message.text
let value = await message.getText();
val value = message.getText()
这将结束驱动程序进程, 默认情况下, 该进程也会关闭浏览器. 无法向此驱动程序实例发送更多命令.
driver.quit();
driver.quit()
driver.Quit();
driver.quit
after(async () => await driver.quit());
driver.quit()
让我们将这8个部分组合成一个完整的脚本, 包括需要使用的库:
按照选项卡底部的链接查看代码示例, 因为它将使用测试运行程序而不是独立文件执行.
package dev.selenium.getting_started;
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;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class FirstScriptTest {
@Test
public void eightComponents() {
WebDriver driver = new ChromeDriver();
driver.get("https://www.selenium.dev/selenium/web/web-form.html");
String title = driver.getTitle();
assertEquals("Web form", title);
driver.manage().timeouts().implicitlyWait(Duration.ofMillis(500));
WebElement textBox = driver.findElement(By.name("my-text"));
WebElement submitButton = driver.findElement(By.cssSelector("button"));
textBox.sendKeys("Selenium");
submitButton.click();
WebElement message = driver.findElement(By.id("message"));
String value = message.getText();
assertEquals("Received!", value);
driver.quit();
}
}
from selenium import webdriver
from selenium.webdriver.common.by import By
def test_eight_components():
driver = webdriver.Chrome()
driver.get("https://www.selenium.dev/selenium/web/web-form.html")
title = driver.title
assert title == "Web form"
driver.implicitly_wait(0.5)
text_box = driver.find_element(by=By.NAME, value="my-text")
submit_button = driver.find_element(by=By.CSS_SELECTOR, value="button")
text_box.send_keys("Selenium")
submit_button.click()
message = driver.find_element(by=By.ID, value="message")
value = message.text
assert value == "Received!"
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()
{
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/web-form.html");
var title = driver.Title;
Assert.AreEqual("Web form", title);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(500);
var textBox = driver.FindElement(By.Name("my-text"));
var submitButton = driver.FindElement(By.TagName("button"));
textBox.SendKeys("Selenium");
submitButton.Click();
var message = driver.FindElement(By.Id("message"));
var value = message.Text;
Assert.AreEqual("Received!", value);
driver.Quit();
}
}
}
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'First Script' do
it 'uses eight components' do
driver = Selenium::WebDriver.for :chrome
driver.get('https://www.selenium.dev/selenium/web/web-form.html')
title = driver.title
expect(title).to eq('Web form')
driver.manage.timeouts.implicit_wait = 500
text_box = driver.find_element(name: 'my-text')
submit_button = driver.find_element(tag_name: 'button')
text_box.send_keys('Selenium')
submit_button.click
message = driver.find_element(id: 'message')
value = message.text
expect(value).to eq('Received!')
driver.quit
end
end
const {By, Builder, Browser} = require('selenium-webdriver');
const {suite} = require('selenium-webdriver/testing');
const assert = require("assert");
suite(function (env) {
describe('First script', function () {
let driver;
before(async function () {
driver = await new Builder().forBrowser('chrome').build();
});
after(async () => await driver.quit());
it('First Selenium script', async function () {
await driver.get('https://www.selenium.dev/selenium/web/web-form.html');
let title = await driver.getTitle();
assert.equal("Web form", title);
await driver.manage().setTimeouts({implicit: 500});
let textBox = await driver.findElement(By.name('my-text'));
let submitButton = await driver.findElement(By.css('button'));
await textBox.sendKeys('Selenium');
await submitButton.click();
let message = await driver.findElement(By.id('message'));
let value = await message.getText();
assert.equal("Received!", value);
});
});
}, { browsers: [Browser.CHROME, Browser.FIREFOX]});
package dev.selenium.getting_started
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://www.selenium.dev/selenium/web/web-form.html")
val title = driver.title
assertEquals("Web form", title)
driver.manage().timeouts().implicitlyWait(Duration.ofMillis(500))
var textBox = driver.findElement(By.name("my-text"))
val submitButton = driver.findElement(By.cssSelector("button"))
textBox.sendKeys("Selenium")
submitButton.click()
val message = driver.findElement(By.id("message"))
val value = message.getText()
assertEquals("Received!", value)
driver.quit()
}
}
If you are using Selenium for testing, you will want to execute your Selenium code using test runner tools.
Many of the code examples in this documentation can be found in our example repositories. There are multiple options in each language, but here is what we are using in our examples:
Install JUnit 5 test runner using a build tool.
In the project’s pom.xml
file, specify the dependency:
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
</dependencies>
and configure the build plugin:
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<includes>
<include>**/*Test.java</include>
<include>**/*Example.java</include>
</includes>
</configuration>
</plugin>
</plugins>
Now, run your tests using:
mvn clean test
In the project’s build.gradle
file, specify the dependency:
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.0'
and add the following in the test
task:
useJUnitPlatform()
Now, run your tests using:
gradle clean test
Install Mocha Test runner using below command in your terminal
Install with npm globally:
npm install -g mocha
or as a development dependency for your project:
npm install --save-dev mocha
and run your tests using below command
mocha firstScript.spec.js
利用你所学的知识, 构建你的Selenium代码.
当您发现需要更多功能时, 请阅读我们的WebDriver文档的其余部分.
如果您使用的是官方支持的语言 (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 标准.
对于大多数情况, 这种实现不会影响终端用户.
主要的例外是 Capabilities
和 Actions
类.
如果测试capabilities的结构不符合 W3C标准,
可能会导致会话无法正常开启.
以下是 W3C WebDriver 标准capabilities列表:
browserName
browserVersion
(替代 version
)platformName
(替代 platform
)acceptInsecureCerts
pageLoadStrategy
proxy
timeouts
unhandledPromptBehavior
可以在以下位置找到标准capabilities的最新列表 W3C WebDriver.
上面列表中未包含的任何capability,
都需要包含供应商前缀.
这适用于浏览器特定capability
以及云供应商特定capability.
例如, 如果您的云供应商为您的测试
使用 build
和 name
capability,
您需要将它们包装在一个 cloud: options
块中
(请与您的云供应商联系以获取适当的前缀).
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)
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 绑定(FindsBy
接口)中
查找元素的工具方法已被删除
因为它们仅供内部使用.
以下代码示例更好地解释了这一点.
使用 findElement*
查找单个元素
driver.findElementByClassName("className");
driver.findElementByCssSelector(".className");
driver.findElementById("elementId");
driver.findElementByLinkText("linkText");
driver.findElementByName("elementName");
driver.findElementByPartialLinkText("partialText");
driver.findElementByTagName("elementTagName");
driver.findElementByXPath("xPath");
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*
查找多个元素
driver.findElementsByClassName("className");
driver.findElementsByCssSelector(".className");
driver.findElementsById("elementId");
driver.findElementsByLinkText("linkText");
driver.findElementsByName("elementName");
driver.findElementsByPartialLinkText("partialText");
driver.findElementsByTagName("elementTagName");
driver.findElementsByXPath("xPath");
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 并升级您的项目依赖项.
升级 Selenium 的过程取决于所使用的构建工具.
我们将涵盖Java 中最常见的
Maven 和
Gradle .
所需的最低 Java 版本仍然是 8.
<dependencies>
<!-- more dependencies ... -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
<!-- more dependencies ... -->
</dependencies>
<dependencies>
<!-- more dependencies ... -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.4.0</version>
</dependency>
<!-- more dependencies ... -->
</dependencies>
进行更改后,
您可以在pom.xml
文件的同一目录中
执行 mvn clean compile
.
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()
}
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.4.0'
}
test {
useJUnitPlatform()
}
进行更改后,
您可以在 build.gradle 文件所在的同一目录中
执行./gradlew clean build
.
要检查所有 Java 版本, 您可以前往 MVNRepository .
在 C# 中获取 Selenium 4 更新的
地方是 NuGet .
在下面包
Selenium.WebDriver
你可以获得更新到最新版本的说明.
在 Visual Studio 内部,
您可以通过 NuGet 包管理器执行:
PM> Install-Package Selenium.WebDriver -Version 4.4.0
使用 Python 的最重要变化是所需的最低版本.
Selenium 4 将至少需要 Python 3.7 或更高版本.
更多详细信息可以在
Python 包索引 .
基于命令行做升级的话, 你可以执行:
pip install selenium==4.4.3
Selenium 4 的更新细节
可以在RubyGems中的gem发现
selenium-webdriver .
要安装最新版本,
您可以执行:
gem install selenium-webdriver
将以下内容添加到你的Gemfile:
gem 'selenium-webdriver', '~> 4.4.0'
可以在 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.4.0"
}
}
这是一组代码示例, 它们将有助于克服 您升级到 Selenium 4 后 可能会遇到的弃用消息.
Timeout 中接收到的参数
已经从期望 (long time, TimeUnit unit)
切换到期待 (Duration duration)
.
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.manage().timeouts().setScriptTimeout(2, TimeUnit.MINUTES);
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
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
的工具方法
withTimeout
和 pollingEvery
已经从期望 (long time, TimeUnit unit)
切换到
期待(Duration duration)
.
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);
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合并到另一组中,
并且改变调用对象.
现在, 需要分配合并操作的结果.
MutableCapabilities capabilities = new MutableCapabilities();
capabilities.setCapability("platformVersion", "Windows 10");
FirefoxOptions options = new FirefoxOptions();
options.setHeadless(true);
options.merge(capabilities);
//作为结果, `options` 对象被修改
MutableCapabilities capabilities = new MutableCapabilities();
capabilities.setCapability("platformVersion", "Windows 10");
FirefoxOptions options = new FirefoxOptions();
options.setHeadless(true);
options = options.merge(capabilities);
// `merge` 调用的结果需要分配给一个对象.
在 GeckoDriver 出现之前,
Selenium 项目有一个驱动程序实现来自动化
Firefox(版本 <48).
但是, 不再需要此实现,
因为在最新版本的 Firefox 中它不起作用.
为避免升级到 Selenium 4 时出现重大问题,
setLegacy
选项将显示为已弃用.
建议停止使用旧的实现
并且只依赖 GeckoDriver.
以下代码将显示在升级之后弃用的 setLegacy
行.
FirefoxOptions options = new FirefoxOptions();
options.setLegacy(true);
BrowserType
BrowserType
接口已经存在很长时间了,
但是其已变为弃用
且推荐使用新的 Browser
接口.
MutableCapabilities capabilities = new MutableCapabilities();
capabilities.setCapability("browserVersion", "92");
capabilities.setCapability("browserName", BrowserType.FIREFOX);
MutableCapabilities capabilities = new MutableCapabilities();
capabilities.setCapability("browserVersion", "92");
capabilities.setCapability("browserName", Browser.FIREFOX);
AddAdditionalCapability
已弃用推荐使用AddAdditionalOption
替代.
以下为一个示例:
var browserOptions = new ChromeOptions();
browserOptions.PlatformName = "Windows 10";
browserOptions.BrowserVersion = "latest";
var cloudOptions = new Dictionary<string, object>();
browserOptions.AddAdditionalCapability("cloud: options", cloudOptions, true);
var browserOptions = new ChromeOptions();
browserOptions.PlatformName = "Windows 10";
browserOptions.BrowserVersion = "latest";
var cloudOptions = new Dictionary<string, object>();
browserOptions.AddAdditionalOption("cloud: options", cloudOptions);
executable_path 已弃用, 请传递一个服务对象
在Selenium 4中,
您需要从服务对象设置驱动程序的 可执行路径
,
以防止出现弃用警告.
(或者不要设置路径, 而是确保所需的驱动程序位于系统路径上.)
from selenium import webdriver
options = webdriver.ChromeOptions()
driver = webdriver.Chrome(
executable_path=CHROMEDRIVER_PATH,
options=options
)
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
options = webdriver.ChromeOptions()
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
启动和停止会话, 用于打开和关闭浏览器.
创建会话对应于W3C的命令 新建会话
会话是通过初始化新的驱动类对象自动创建的.
每种语言都允许使用来自这些类 (或等效类) 之一的参数创建会话:
启动本地驱动的首要唯一参数 包括在本地计算机上有关启动所需驱动服务的信息.
用于启动远程驱动的首要唯一参数包括有关在何处执行代码的信息. 请浏览 远程驱动章节中的详细信息
退出会话对应于W3C的命令 删除会话.
重要提示: quit
方法与 close
方法不同,
建议始终使用 quit
来结束会话
在 Selenium 3 中, capabilities是借助"Desired Capabilities"类定义于会话中的. 从 Selenium 4 开始, 您必须使用浏览器选项类. 对于远程驱动程序会话, 浏览器选项实例是必需的, 因为它确定将使用哪个浏览器.
这些选项在 Capabilities 的 w3c 规范中进行了描述.
每个浏览器都有 自定义选项 , 是规范定义之外的内容.
Browser name is set by default when using an Options class instance.
This capability is optional, this is used to set the available browser version at remote end. In recent versions of Selenium, if the version is not found on the system, it will be automatically downloaded by Selenium Manager
共有三种类型的页面加载策略.
页面加载策略可以在此链接查询 document.readyState , 如下表所述:
策略 | 就绪状态 | 备注 |
---|---|---|
normal | complete | 默认值, 等待所有资源下载 |
eager | interactive | DOM 访问已准备就绪, 但诸如图像的其他资源可能仍在加载 |
none | Any | 完全不会阻塞 WebDriver |
文档的 document.readyState
属性描述当前文档的加载状态.
当通过URL导航到新页面时, 默认情况下, WebDriver将暂缓完成导航方法 (例如, driver.navigate().get())直到文档就绪状态完成. 这 并非意味着该页面已完成加载, 特别是对于使用 JavaScript 在就绪状态返回完成后 动态加载内容单页应用程序的站点. 另请注意此行为不适用于单击元素或提交表单后出现的导航行为.
如果由于下载对自动化不重要的资源(例如, 图像、css、js)
而需要很长时间才能加载页面,
您可以将默认参数normal
更改为
eager
或 none
以加快会话加载速度.
此值适用于整个会话,
因此请确保您的 等待策略
足够普适.
WebDriver一直等到 load 事件触发并返回.
import org.openqa.selenium.PageLoadStrategy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.chrome.ChromeDriver;
public class pageLoadStrategy {
public static void main(String[] args) {
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setPageLoadStrategy(PageLoadStrategy.NORMAL);
WebDriver driver = new ChromeDriver(chromeOptions);
try {
// Navigate to Url
driver.get("https://google.com");
} finally {
driver.quit();
}
}
}
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.page_load_strategy = 'normal'
driver = webdriver.Chrome(options=options)
driver.get("http://www.google.com")
driver.quit()
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace pageLoadStrategy {
class pageLoadStrategy {
public static void Main(string[] args) {
var chromeOptions = new ChromeOptions();
chromeOptions.PageLoadStrategy = PageLoadStrategy.Normal;
IWebDriver driver = new ChromeDriver(chromeOptions);
try {
driver.Navigate().GoToUrl("https://example.com");
} finally {
driver.Quit();
}
}
}
}
require 'selenium-webdriver'
options = Selenium::WebDriver::Options.chrome
options.page_load_strategy = :normal
driver = Selenium::WebDriver.for :chrome, options: options
driver.get('https://www.google.com')
it('Navigate using normal page loading strategy', async function () {
let driver = await env
.builder()
.setChromeOptions(options.setPageLoadStrategy('normal'))
.build();
await driver.get('https://www.selenium.dev/selenium/web/blank.html');
import org.openqa.selenium.PageLoadStrategy
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions
fun main() {
val chromeOptions = ChromeOptions()
chromeOptions.setPageLoadStrategy(PageLoadStrategy.NORMAL)
val driver = ChromeDriver(chromeOptions)
try {
driver.get("https://www.google.com")
}
finally {
driver.quit()
}
}
WebDriver一直等到 DOMContentLoaded 事件触发并返回.
import org.openqa.selenium.PageLoadStrategy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.chrome.ChromeDriver;
public class pageLoadStrategy {
public static void main(String[] args) {
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setPageLoadStrategy(PageLoadStrategy.EAGER);
WebDriver driver = new ChromeDriver(chromeOptions);
try {
// Navigate to Url
driver.get("https://google.com");
} finally {
driver.quit();
}
}
}
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.page_load_strategy = 'eager'
driver = webdriver.Chrome(options=options)
driver.get("http://www.google.com")
driver.quit()
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace pageLoadStrategy {
class pageLoadStrategy {
public static void Main(string[] args) {
var chromeOptions = new ChromeOptions();
chromeOptions.PageLoadStrategy = PageLoadStrategy.Eager;
IWebDriver driver = new ChromeDriver(chromeOptions);
try {
driver.Navigate().GoToUrl("https://example.com");
} finally {
driver.Quit();
}
}
}
}
require 'selenium-webdriver'
options = Selenium::WebDriver::Options.chrome
options.page_load_strategy = :eager
driver = Selenium::WebDriver.for :chrome, options: options
driver.get('https://www.google.com')
it('Navigate using eager page loading strategy', async function () {
let driver = await env
.builder()
.setChromeOptions(options.setPageLoadStrategy('eager'))
.build();
await driver.get('https://www.selenium.dev/selenium/web/blank.html');
import org.openqa.selenium.PageLoadStrategy
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions
fun main() {
val chromeOptions = ChromeOptions()
chromeOptions.setPageLoadStrategy(PageLoadStrategy.EAGER)
val driver = ChromeDriver(chromeOptions)
try {
driver.get("https://www.google.com")
}
finally {
driver.quit()
}
}
WebDriver 仅等待初始页面已下载.
import org.openqa.selenium.PageLoadStrategy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.chrome.ChromeDriver;
public class pageLoadStrategy {
public static void main(String[] args) {
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setPageLoadStrategy(PageLoadStrategy.NONE);
WebDriver driver = new ChromeDriver(chromeOptions);
try {
// Navigate to Url
driver.get("https://google.com");
} finally {
driver.quit();
}
}
}
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.page_load_strategy = 'none'
driver = webdriver.Chrome(options=options)
driver.get("http://www.google.com")
driver.quit()
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace pageLoadStrategy {
class pageLoadStrategy {
public static void Main(string[] args) {
var chromeOptions = new ChromeOptions();
chromeOptions.PageLoadStrategy = PageLoadStrategy.None;
IWebDriver driver = new ChromeDriver(chromeOptions);
try {
driver.Navigate().GoToUrl("https://example.com");
} finally {
driver.Quit();
}
}
}
}
require 'selenium-webdriver'
options = Selenium::WebDriver::Options.chrome
options.page_load_strategy = :none
driver = Selenium::WebDriver.for :chrome, options: options
driver.get('https://www.google.com')
it('Navigate using none page loading strategy', async function () {
let driver = await env
.builder()
.setChromeOptions(options.setPageLoadStrategy('none'))
.build();
await driver.get('https://www.selenium.dev/selenium/web/blank.html');
import org.openqa.selenium.PageLoadStrategy
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions
fun main() {
val chromeOptions = ChromeOptions()
chromeOptions.setPageLoadStrategy(PageLoadStrategy.NONE)
val driver = ChromeDriver(chromeOptions)
try {
driver.get("https://www.google.com")
}
finally {
driver.quit()
}
}
这标识了远端的操作系统,
获取 platformName
将返回操作系统的名称.
在基于云的供应者中,
设置 platformName
将在远程端设置操作系统.
此功能检查在会话期间导航时
是否使用了过期的 (或) 无效的 TLS Certificate
.
如果将功能设置为 false
,
则页面浏览遇到任何域证书问题时,
将返回insecure certificate error .
如果设置为 true
, 则浏览器将信任无效证书.
默认情况下, 此功能将信任所有自签名证书.
设置后, acceptInsecureCerts
功能将在整个会话中生效.
WebDriver session
具有一定的 session timeout
间隔,
在此间隔内, 用户可以控制执行脚本或从浏览器检索信息的行为.
每个会话超时都配置有不同 timeouts
的组合,
如下所述:
指定在当前浏览上下文中, 中断正在执行脚本的时机. WebDriver创建新会话时, 将设置默认的超时时间为 30,000 .
指定在当前浏览上下文中, 加载网页的时间间隔. WebDriver创建新会话时, 默认设置超时时间为 300,000 . 如果页面加载限制了给定 (或默认) 的时间范围, 则该脚本将被 TimeoutException 停止.
指定在定位元素时, 等待隐式元素定位策略的时间. WebDriver创建新会话时, 将设置默认超时时间为 0 .
指定当前会话 user prompt handler
的状态.
默认为 dismiss and notify state .
这定义了在远端出现用户提示时必须采取的措施.
该行为由unhandledPromptBehavior
功能定义,
具有以下状态:
新功能用于是否对 类型为文件的输入(input type=file) 元素进行严格的交互性检查. 默认关闭严格性检查, 在将 元素的Send Keys 方法作用于隐藏的文件上传时, 会有控制方面的行为区别.
代理服务器充当客户端和服务器之间的请求中介. 简述而言, 流量将通过代理服务器流向您请求的地址, 然后返回.
使用代理服务器用于Selenium的自动化脚本, 可能对以下方面有益:
如果您在公司环境中, 并且浏览器无法连接到URL, 则最有可能是因为环境, 需要借助代理进行访问.
Selenium WebDriver提供了如下设置代理的方法
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
public class ProxyTest {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.setHttpProxy("<HOST:PORT>");
ChromeOptions options = new ChromeOptions();
options.setCapability("proxy", proxy);
WebDriver driver = new ChromeDriver(options);
driver.get("https://www.google.com/");
driver.manage().window().maximize();
driver.quit();
}
}
from selenium import webdriver
PROXY = "<HOST:PORT>"
webdriver.DesiredCapabilities.FIREFOX['proxy'] = {
"httpProxy": PROXY,
"ftpProxy": PROXY,
"sslProxy": PROXY,
"proxyType": "MANUAL",
}
with webdriver.Firefox() as driver:
# Open URL
driver.get("https://selenium.dev")
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
public class ProxyTest{
public static void Main() {
ChromeOptions options = new ChromeOptions();
Proxy proxy = new Proxy();
proxy.Kind = ProxyKind.Manual;
proxy.IsAutoDetect = false;
proxy.SslProxy = "<HOST:PORT>";
options.Proxy = proxy;
options.AddArgument("ignore-certificate-errors");
IWebDriver driver = new ChromeDriver(options);
driver.Navigate().GoToUrl("https://www.selenium.dev/");
}
}
# this code was written with Selenium 4
proxy = Selenium::WebDriver::Proxy.new(http: '<HOST:PORT>')
cap = Selenium::WebDriver::Remote::Capabilities.chrome(proxy: proxy)
driver = Selenium::WebDriver.for(:chrome, capabilities: cap)
driver.get('http://google.com')
let webdriver = require('selenium-webdriver');
let chrome = require('selenium-webdriver/chrome');
let proxy = require('selenium-webdriver/proxy');
let opts = new chrome.Options();
(async function example() {
opts.setProxy(proxy.manual({http: '<HOST:PORT>'}));
let driver = new webdriver.Builder()
.forBrowser('chrome')
.setChromeOptions(opts)
.build();
try {
await driver.get("https://selenium.dev");
}
finally {
await driver.quit();
}
}());
import org.openqa.selenium.Proxy
import org.openqa.selenium.WebDriver
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions
class proxyTest {
fun main() {
val proxy = Proxy()
proxy.setHttpProxy("<HOST:PORT>")
val options = ChromeOptions()
options.setCapability("proxy", proxy)
val driver: WebDriver = ChromeDriver(options)
driver["https://www.google.com/"]
driver.manage().window().maximize()
driver.quit()
}
}
允许您为HTTP库设置各种参数.
服务类用于管理驱动程序的启动和停止. They can not be used with a Remote WebDriver session.
Service classes allow you to specify information about the driver, like location and which port to use. They also let you specify what arguments get passed to the command line. Most of the useful arguments are related to logging.
To start a driver with a default service instance:
ChromeDriverService service = new ChromeDriverService.Builder()
.usingDriverExecutable(getDriverLocation())
.build();
service = webdriver.ChromeService()
driver = webdriver.Chrome(service=service)
var service = ChromeDriverService.CreateDefaultService();
driver = new ChromeDriver(service);
service = Selenium::WebDriver::Service.chrome
@driver = Selenium::WebDriver.for :chrome, service: service
Note: If you are using Selenium 4.6 or greater, you shouldn’t need to set a driver location. If you can not update Selenium or have an advanced use case here is how to specify the driver location:
.usingDriverExecutable(getDriverLocation())
service = webdriver.ChromeService(executable_path=chromedriver_path)
var service = ChromeDriverService.CreateDefaultService(GetDriverLocation());
If you want the driver to run on a specific port, you may specify it as follows:
.usingPort(1234)
service.Port = 1234;
Logging functionality varies between browsers. Most browsers allow you to specify location and level of logs. Take a look at the respective browser page:
您可以如本地一样, 使用远程WebDriver. 主要区别在于需要配置远程WebDriver, 以便可以在不同的计算机上运行测试.
远程WebDriver由两部分组成:客户端和服务端. 客户端是您的WebDriver测试,而服务端仅仅是可以被托管于任何现代Java EE应用服务器的Java Servlet.
要运行远程WebDriver客户端, 我们首先需要连接到RemoteWebDriver. 为此, 我们将URL指向运行测试的服务器的地址. 为了自定义我们的配置, 我们设置了既定的功能. 下面是一个实例化样例, 其指向我们的远程Web服务器 www.example.com 的远程WebDriver对象, 并在Firefox上运行测试.
FirefoxOptions firefoxOptions = new FirefoxOptions();
WebDriver driver = new RemoteWebDriver(new URL("http://www.example.com"), firefoxOptions);
driver.get("http://www.google.com");
driver.quit();
from selenium import webdriver
firefox_options = webdriver.FirefoxOptions()
driver = webdriver.Remote(
command_executor='http://www.example.com',
options=firefox_options
)
driver.get("http://www.google.com")
driver.quit()
FirefoxOptions firefoxOptions = new FirefoxOptions();
IWebDriver driver = new RemoteWebDriver(new Uri("http://www.example.com"), firefoxOptions);
driver.Navigate().GoToUrl("http://www.google.com");
driver.Quit();
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :remote, url: "http://www.example.com", desired_capabilities: :firefox
driver.get "http://www.google.com"
driver.close
const { Builder, Capabilities } = require("selenium-webdriver");
var capabilities = Capabilities.firefox();
(async function helloSelenium() {
let driver = new Builder()
.usingServer("http://example.com")
.withCapabilities(capabilities)
.build();
try {
await driver.get('http://www.google.com');
} finally {
await driver.quit();
}
})();
firefoxOptions = FirefoxOptions()
driver: WebDriver = RemoteWebDriver(URL("http://www.example.com"), firefoxOptions)
driver.get("http://www.google.com")
driver.quit()
为了进一步自定义测试配置, 我们可以添加其他既定的功能.
例如, 假设您想使用Chrome版本67 在Windows XP上运行Chrome:
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setCapability("browserVersion", "67");
chromeOptions.setCapability("platformName", "Windows XP");
WebDriver driver = new RemoteWebDriver(new URL("http://www.example.com"), chromeOptions);
driver.get("http://www.google.com");
driver.quit();
from selenium import webdriver
chrome_options = webdriver.ChromeOptions()
chrome_options.set_capability("browserVersion", "67")
chrome_options.set_capability("platformName", "Windows XP")
driver = webdriver.Remote(
command_executor='http://www.example.com',
options=chrome_options
)
driver.get("http://www.google.com")
driver.quit()
var chromeOptions = new ChromeOptions();
chromeOptions.BrowserVersion = "67";
chromeOptions.PlatformName = "Windows XP";
IWebDriver driver = new RemoteWebDriver(new Uri("http://www.example.com"), chromeOptions);
driver.Navigate().GoToUrl("http://www.google.com");
driver.Quit();
caps = Selenium::WebDriver::Remote::Capabilities.chrome
caps.platform = Windows XP
caps.version = 67
driver = Selenium::WebDriver.for :remote, :url => "http://www.example.com", :desired_capabilities => caps
const { Builder } = require("selenium-webdriver");
const chrome = require("selenium-webdriver/chrome");
let opts = new chrome.Options();
opts.setAcceptInsecureCerts(true);
opts.setBrowserVersion('67');
opts.setPlatform('Windows XP');
(async function helloSelenium() {
let driver = new Builder()
.usingServer("http://example.com")
.forBrowser('chrome')
.setChromeOptions(opts)
.build();
try {
await driver.get('http://www.google.com');
}
finally {
await driver.quit();
}
})();
val chromeOptions = ChromeOptions()
chromeOptions.setCapability("browserVersion", "67")
chromeOptions.setCapability("platformName", "Windows XP")
val driver: WebDriver = RemoteWebDriver(URL("http://www.example.com"), chromeOptions)
driver.get("http://www.google.com")
driver.quit()
本地文件检测器允许将文件从客户端计算机传输到远程服务器. 例如, 如果测试需要将文件上传到Web应用程序, 则远程WebDriver可以在运行时 将文件从本地计算机自动传输到远程Web服务器. 这允许从运行测试的远程计算机上载文件. 默认情况下未启用它, 可以通过以下方式启用:
driver.setFileDetector(new LocalFileDetector());
from selenium.webdriver.remote.file_detector import LocalFileDetector
driver.file_detector = LocalFileDetector()
var allowsDetection = this.driver as IAllowsFileDetection;
if (allowsDetection != null)
{
allowsDetection.FileDetector = new LocalFileDetector();
}
@driver.file_detector = lambda do |args|
# args => ["/path/to/file"]
str = args.first.to_s
str if File.exist?(str)
end
var remote = require('selenium-webdriver/remote');
driver.setFileDetector(new remote.FileDetector);
driver.fileDetector = LocalFileDetector()
定义上述代码后, 您可以通过以下方式在测试中上传文件:
driver.get("http://sso.dev.saucelabs.com/test/guinea-file-upload");
WebElement upload = driver.findElement(By.id("myfile"));
upload.sendKeys("/Users/sso/the/local/path/to/darkbulb.jpg");
driver.get("http://sso.dev.saucelabs.com/test/guinea-file-upload")
driver.find_element(By.ID, "myfile").send_keys("/Users/sso/the/local/path/to/darkbulb.jpg")
driver.Navigate().GoToUrl("http://sso.dev.saucelabs.com/test/guinea-file-upload");
IWebElement upload = driver.FindElement(By.Id("myfile"));
upload.SendKeys(@"/Users/sso/the/local/path/to/darkbulb.jpg");
@driver.navigate.to "http://sso.dev.saucelabs.com/test/guinea-file-upload"
element = @driver.find_element(:id, 'myfile')
element.send_keys "/Users/sso/SauceLabs/sauce/hostess/maitred/maitred/public/images/darkbulb.jpg"
driver.get("http://sso.dev.saucelabs.com/test/guinea-file-upload");
var upload = driver.findElement(By.id("myfile"));
upload.sendKeys("/Users/sso/the/local/path/to/darkbulb.jpg");
driver.get("http://sso.dev.saucelabs.com/test/guinea-file-upload")
val upload: WebElement = driver.findElement(By.id("myfile"))
upload.sendKeys("/Users/sso/the/local/path/to/darkbulb.jpg")
此功能仅适用于Java客户端绑定 (Beta版以后). 远程WebDriver客户端向Selenium网格服务器发送请求, 后者将请求传递给WebDriver. 应该在服务器端和客户端启用跟踪, 以便端到端地追踪HTTP请求. 两端都应该有一个指向可视化框架的追踪导出器设置. 默认情况下, 对客户端和服务器都启用追踪. 若设置可视化框架Jaeger UI及Selenium Grid 4, 请参阅所需版本的追踪设置 .
对于客户端设置, 请执行以下步骤.
可以使用Maven安装追踪导出器的外部库. 在项目pom.xml中添加 opentelemetry-exporter-jaeger 和 grpc-netty 的依赖项:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-jaeger</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>1.35.0</version>
</dependency>
System.setProperty("otel.traces.exporter", "jaeger");
System.setProperty("otel.exporter.jaeger.endpoint", "http://localhost:14250");
System.setProperty("otel.resource.attributes", "service.name=selenium-java-client");
ImmutableCapabilities capabilities = new ImmutableCapabilities("browserName", "chrome");
WebDriver driver = new RemoteWebDriver(new URL("http://www.example.com"), capabilities);
driver.get("http://www.google.com");
driver.quit();
有关所需Selenium版本 及其外部依赖关系版本等更多信息, 请参阅追踪设置 .
更多信息请访问:
Some browser specific functionalities require workarounds as mentioned in this issue.
每个浏览器都有定制和特有的功能。
默认情况下,Selenium 4与Chrome v75及更高版本兼容. 但是请注意Chrome浏览器的版本与chromedriver的主版本需要匹配.
所有浏览器的通用功能请看这 Options page.
Chrome浏览器的特有功能可以在谷歌的页面找到: Capabilities & ChromeOptions
基于默认选项的Chrome浏览器会话看起来是这样:
ChromeOptions options = new ChromeOptions();
driver = new ChromeDriver(options);
options = webdriver.ChromeOptions()
driver = webdriver.Chrome(options=options)
var options = new ChromeOptions();
driver = new ChromeDriver(options);
options = Selenium::WebDriver::Options.chrome
@driver = Selenium::WebDriver.for :chrome, options: options
const Options = new Chrome.Options();
let driver = await env
.builder()
.setChromeOptions(Options)
.build();
下面是一些不同功能的常见示例:
The args
parameter is for a list of command line switches to be used when starting the browser.
There are two excellent resources for investigating these arguments:
Commonly used args include --start-maximized
, --headless=new
and --user-data-dir=...
Add an argument to options:
options.addArguments("--start-maximized");
options.add_argument("--start-maximized")
options.AddArgument("--start-maximized");
options.args << '--maximize'
let driver = await env
.builder()
.setChromeOptions(options.addArguments('--headless=new'))
.build();
binary
参数接收一个使用浏览器的备用路径,通过这个参数你可以使用chromedriver 去驱动各种基于Chromium 内核的浏览器.
添加一个浏览器地址到选项中:
options.setBinary(getChromeLocation());
options.binary_location = CHROME_LOCATION
options.BinaryLocation = GetChromeLocation();
options.binary = chrome_location
let driver = await env
.builder()
.setChromeOptions(options.setChromeBinaryPath(`Path to chrome binary`))
.build();
extensions
参数接受crx文件. As for unpacked directories,
please use the load-extension
argument instead, as mentioned in
this post.
添加一个扩展程序到选项中:
options.addExtensions(extensionPath);
options.add_extension(path)
options.AddExtension(extensionFilePath);
options.add_extension(extension_file_path)
const options = new Chrome.Options();
let driver = await env
.builder()
.setChromeOptions(options.addExtensions(['./test/resources/extensions/webextensions-selenium-example.crx']))
.build();
将 detach
参数设置为true将在驱动过程结束后保持浏览器的打开状态.
添加一个布尔值到选项中:
Note: This is already the default behavior in Java.
options.add_experimental_option("detach", True)
Note: This is already the default behavior in .NET.
options.detach = true
let driver = await env
.builder()
.setChromeOptions(options.detachDriver(true))
.build();
Chrome 添加了各种参数,如果你不希望添加某些参数,可以将其传入 excludeSwitches
.
一个常见的例子是重新打开弹出窗口阻止程序.
A full list of default arguments
can be parsed from the
Chromium Source Code
设置排除参数至选项中:
options.setExperimentalOption("excludeSwitches", ImmutableList.of("disable-popup-blocking"));
options.add_experimental_option('excludeSwitches', ['disable-popup-blocking'])
options.AddExcludedArgument("disable-popup-blocking");
options.exclude_switches << 'enable-automation'
let driver = await env
.builder()
.setChromeOptions(options.excludeSwitches('enable-automation'))
.build();
Examples for creating a default Service object, and for setting driver location and port can be found on the Driver Service page.
Getting driver logs can be helpful for debugging issues. The Service class lets you direct where the logs will go. Logging output is ignored unless the user directs it somewhere.
To change the logging output to save to a specific file:
.withLogFile(getLogLocation())
Note: Java also allows setting file output by System Property:
Property key: ChromeDriverService.CHROME_DRIVER_LOG_PROPERTY
Property value: String representing path to log file
service.LogPath = GetLogLocation();
To change the logging output to display in the console as STDOUT:
.withLogOutput(System.out)
Note: Java also allows setting console output by System Property;
Property key: ChromeDriverService.CHROME_DRIVER_LOG_PROPERTY
Property value: DriverService.LOG_STDOUT
or DriverService.LOG_STDERR
service = webdriver.ChromeService(log_output=subprocess.STDOUT)
$stdout
and $stderr
are both valid values
service.log = $stdout
There are 6 available log levels: ALL
, DEBUG
, INFO
, WARNING
, SEVERE
, and OFF
.
Note that --verbose
is equivalent to --log-level=ALL
and --silent
is equivalent to --log-level=OFF
,
so this example is just setting the log level generically:
.withLogLevel(ChromiumDriverLogLevel.DEBUG)
Note: Java also allows setting log level by System Property:
Property key: ChromeDriverService.CHROME_DRIVER_LOG_LEVEL_PROPERTY
Property value: String representation of ChromiumDriverLogLevel
enum
service = webdriver.ChromeService(service_args=['--log-level=DEBUG'], log_output=subprocess.STDOUT)
There are 2 features that are only available when logging to a file:
To use them, you need to also explicitly specify the log path and log level. The log output will be managed by the driver, not the process, so minor differences may be seen.
.withAppendLog(true)
.withReadableTimestamp(true)
Note: Java also allows toggling these features by System Property:
Property keys: ChromeDriverService.CHROME_DRIVER_APPEND_LOG_PROPERTY
and ChromeDriverService.CHROME_DRIVER_READABLE_TIMESTAMP
Property value: "true"
or "false"
service = webdriver.ChromeService(service_args=['--append-log', '--readable-timestamp'], log_output=log_path)
service.args << '--append-log'
service.args << '--readable-timestamp'
Chromedriver and Chrome browser versions should match, and if they don’t the driver will error. If you disable the build check, you can force the driver to be used with any version of Chrome. Note that this is an unsupported feature, and bugs will not be investigated.
.withBuildCheckDisabled(true)
Note: Java also allows disabling build checks by System Property:
Property key: ChromeDriverService.CHROME_DRIVER_DISABLE_BUILD_CHECK
Property value: "true"
or "false"
service = webdriver.ChromeService(service_args=['--disable-build-check'], log_output=subprocess.STDOUT)
service.DisableBuildCheck = true;
你可以驱动 Chrome Cast 设备,包括共享选项卡
您可以模拟各种网络条件.
The following examples are for local webdrivers. For remote webdrivers, please refer to the Remote WebDriver page.
See the Chrome DevTools section for more information about using Chrome DevTools
微软Edge是用Chromium实现的,最早支持版本是v79. 与Chrome类似, Edge驱动的主版本号必须与Edge浏览器的主要版本匹配.
在 Chrome 页面 上找到的所有capabilities和选项也适用于Edge.
Capabilities common to all browsers are described on the Options page.
Capabilities unique to Chromium are documented at Google’s page for Capabilities & ChromeOptions
使用基本定义的选项启动 Edge 会话如下所示:
EdgeOptions options = new EdgeOptions();
driver = new EdgeDriver(options);
options = webdriver.EdgeOptions()
driver = webdriver.Edge(options=options)
var options = new EdgeOptions();
driver = new EdgeDriver(options);
options = Selenium::WebDriver::Options.edge
@driver = Selenium::WebDriver.for :edge, options: options
driver = await env.builder()
.setEdgeOptions(options)
.build();
});
The args
parameter is for a list of command line switches to be used when starting the browser.
There are two excellent resources for investigating these arguments:
Commonly used args include --start-maximized
and --headless=new
and --user-data-dir=...
Add an argument to options:
options.addArguments("--start-maximized");
options.add_argument("--start-maximized")
options.AddArgument("--start-maximized");
options.args << '--maximize'
The binary
parameter takes the path of an alternate location of browser to use. With this parameter you can
use chromedriver to drive various Chromium based browsers.
Add a browser location to options:
options.setBinary(getEdgeLocation());
options.binary_location = EDGE_LOCATION
options.BinaryLocation = GetEdgeLocation();
options.binary = edge_location
The extensions
parameter accepts crx files. As for unpacked directories,
please use the load-extension
argument instead, as mentioned in
this post.
Add an extension to options:
options.addExtensions(extensionPath);
options.add_extension(path)
options.AddExtension(extensionFilePath);
options.add_extension(extension_file_path)
Setting the detach
parameter to true will keep the browser open after the process has ended,
so long as the quit command is not sent to the driver.
Note: This is already the default behavior in Java.
Note: This is already the default behavior in .NET.
options.detach = true
MSEdgedriver has several default arguments it uses to start the browser.
If you do not want those arguments added, pass them into excludeSwitches
.
A common example is to turn the popup blocker back on. A full list of default arguments
can be parsed from the
Chromium Source Code
Set excluded arguments on options:
options.setExperimentalOption("excludeSwitches", ImmutableList.of("disable-popup-blocking"));
driver = webdriver.Edge(options=options)
options.AddExcludedArgument("disable-popup-blocking");
options.exclude_switches << 'enable-automation'
Examples for creating a default Service object, and for setting driver location and port can be found on the Driver Service page.
Getting driver logs can be helpful for debugging issues. The Service class lets you direct where the logs will go. Logging output is ignored unless the user directs it somewhere.
To change the logging output to save to a specific file:
.withLogFile(getLogLocation())
Note: Java also allows setting file output by System Property:
Property key: EdgeDriverService.EDGE_DRIVER_LOG_PROPERTY
Property value: String representing path to log file
driver = webdriver.Edge(service=service)
service.LogPath = GetLogLocation();
To change the logging output to display in the console as STDOUT:
.withLogOutput(System.out)
Note: Java also allows setting console output by System Property;
Property key: EdgeDriverService.EDGE_DRIVER_LOG_PROPERTY
Property value: DriverService.LOG_STDOUT
or DriverService.LOG_STDERR
$stdout
and $stderr
are both valid values
service.log = $stdout
There are 6 available log levels: ALL
, DEBUG
, INFO
, WARNING
, SEVERE
, and OFF
.
Note that --verbose
is equivalent to --log-level=ALL
and --silent
is equivalent to --log-level=OFF
,
so this example is just setting the log level generically:
.withLoglevel(ChromiumDriverLogLevel.DEBUG)
Note: Java also allows setting log level by System Property:
Property key: EdgeDriverService.EDGE_DRIVER_LOG_LEVEL_PROPERTY
Property value: String representation of ChromiumDriverLogLevel
enum
driver = webdriver.Edge(service=service)
There are 2 features that are only available when logging to a file:
To use them, you need to also explicitly specify the log path and log level. The log output will be managed by the driver, not the process, so minor differences may be seen.
.withAppendLog(true)
.withReadableTimestamp(true)
Note: Java also allows toggling these features by System Property:
Property keys: EdgeDriverService.EDGE_DRIVER_APPEND_LOG_PROPERTY
and EdgeDriverService.EDGE_DRIVER_READABLE_TIMESTAMP
Property value: "true"
or "false"
driver = webdriver.Edge(service=service)
service.args << '--append-log'
service.args << '--readable-timestamp'
Edge browser and msedgedriver versions should match, and if they don’t the driver will error. If you disable the build check, you can force the driver to be used with any version of Edge. Note that this is an unsupported feature, and bugs will not be investigated.
.withBuildCheckDisabled(true)
Note: Java also allows disabling build checks by System Property:
Property key: EdgeDriverService.EDGE_DRIVER_DISABLE_BUILD_CHECK
Property value: "true"
or "false"
driver = webdriver.Edge(service=service)
service.DisableBuildCheck = true;
微软Edge可以被"Internet Explorer兼容模式"驱动, 该模式使用Internet Explorer驱动类与微软Edge结合使用. 阅读 Internet Explorer 页面 了解更多详情.
Some browsers have implemented additional features that are unique to them.
You can drive Chrome Cast devices with Edge, including sharing tabs
You can simulate various network conditions.
See the Chrome DevTools section for more information about using DevTools in Edge
Selenium 4 requires Firefox 78 or greater. It is recommended to always use the latest version of geckodriver.
Capabilities common to all browsers are described on the Options page.
Capabilities unique to Firefox can be found at Mozilla’s page for firefoxOptions
Starting a Firefox session with basic defined options looks like this:
FirefoxOptions options = new FirefoxOptions();
driver = new FirefoxDriver(options);
options = webdriver.FirefoxOptions()
driver = webdriver.Firefox(options=options)
var options = new FirefoxOptions();
driver = new FirefoxDriver(options);
options = Selenium::WebDriver::Options.firefox
@driver = Selenium::WebDriver.for :firefox, options: options
let options = new firefox.Options();
driver = await env.builder()
.setFirefoxOptions(options)
.build();
Here are a few common use cases with different capabilities:
The args
parameter is for a list of Command line switches used when starting the browser.
Commonly used args include -headless
and "-profile", "/path/to/profile"
Add an argument to options:
options.addArguments("-headless");
options.add_argument("-headless")
options.AddArgument("-headless");
options.args << '-headless'
let driver = await env.builder()
.setFirefoxOptions(options.addArguments('--headless'))
.build();
The binary
parameter takes the path of an alternate location of browser to use. For example, with this parameter you can
use geckodriver to drive Firefox Nightly instead of the production version when both are present on your computer.
Add a browser location to options:
options.setBinary(getFirefoxLocation());
options.binary_location = FIREFOX_LOCATION
options.BinaryLocation = GetFirefoxLocation();
options.binary = firefox_location
There are several ways to work with Firefox profiles
FirefoxProfile profile = new FirefoxProfile();
FirefoxOptions options = new FirefoxOptions();
options.setProfile(profile);
driver = new RemoteWebDriver(options);
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
options=Options()
firefox_profile = FirefoxProfile()
firefox_profile.set_preference("javascript.enabled", False)
options.profile = firefox_profile
var options = new FirefoxOptions();
var profile = new FirefoxProfile();
options.Profile = profile;
var driver = new RemoteWebDriver(options);
profile = Selenium::WebDriver::Firefox::Profile.new
profile['browser.download.dir'] = "/tmp/webdriver-downloads"
options = Selenium::WebDriver::Firefox::Options.new(profile: profile)
driver = Selenium::WebDriver.for :firefox, options: options
const { Builder } = require("selenium-webdriver");
const firefox = require('selenium-webdriver/firefox');
const options = new firefox.Options();
let profile = '/path to custom profile';
options.setProfile(profile);
const driver = new Builder()
.forBrowser('firefox')
.setFirefoxOptions(options)
.build();
val options = FirefoxOptions()
options.profile = FirefoxProfile()
driver = RemoteWebDriver(options)
Service settings common to all browsers are described on the Service page.
Getting driver logs can be helpful for debugging various issues. The Service class lets you direct where the logs will go. Logging output is ignored unless the user directs it somewhere.
To change the logging output to save to a specific file:
.withLogFile(getLogLocation())
Note: Java also allows setting file output by System Property:
Property key: GeckoDriverService.GECKO_DRIVER_LOG_PROPERTY
Property value: String representing path to log file
service = webdriver.FirefoxService(log_path=log_path, service_args=['--log', 'debug'])
To change the logging output to display in the console:
.withLogOutput(System.out)
Note: Java also allows setting console output by System Property;
Property key: GeckoDriverService.GECKO_DRIVER_LOG_PROPERTY
Property value: DriverService.LOG_STDOUT
or DriverService.LOG_STDERR
service = webdriver.FirefoxService(log_output=subprocess.STDOUT)
There are 7 available log levels: fatal
, error
, warn
, info
, config
, debug
, trace
.
If logging is specified the level defaults to info
.
Note that -v
is equivalent to -log debug
and -vv
is equivalent to log trace
,
so this examples is just for setting the log level generically:
.withLogLevel(FirefoxDriverLogLevel.DEBUG)
Note: Java also allows setting log level by System Property:
Property key: GeckoDriverService.GECKO_DRIVER_LOG_LEVEL_PROPERTY
Property value: String representation of FirefoxDriverLogLevel
enum
service = webdriver.FirefoxService(log_path=log_path, service_args=['--log', 'debug'])
The driver logs everything that gets sent to it, including string representations of large binaries, so Firefox truncates lines by default. To turn off truncation:
.withTruncatedLogs(false)
Note: Java also allows setting log level by System Property:
Property key: GeckoDriverService.GECKO_DRIVER_LOG_NO_TRUNCATE
Property value: "true"
or "false"
service = webdriver.FirefoxService(service_args=['--log-no-truncate', '--log', 'debug'], log_path=log_path)
The default directory for profiles is the system temporary directory. If you do not have access to that directory, or want profiles to be created some place specific, you can change the profile root directory:
.withProfileRoot(getTempDirectory())
Note: Java also allows setting log level by System Property:
Property key: GeckoDriverService.GECKO_DRIVER_PROFILE_ROOT
Property value: String representing path to profile root directory
service = webdriver.FirefoxService(service_args=['--profile-root', temp_dir])
Unlike Chrome, Firefox extensions are not added as part of capabilities as mentioned in this issue, they are created after starting the driver.
The following examples are for local webdrivers. For remote webdrivers, please refer to the Remote WebDriver page.
A signed xpi file you would get from Mozilla Addon page
driver.installExtension(xpiPath);
driver.install_addon(addon_path)
driver.InstallAddOnFromFile(Path.GetFullPath(extensionFilePath));
driver.install_addon(extension_file_path)
const xpiPath = path.resolve('./test/resources/extensions/selenium-example.xpi')
let driver = await env.builder().build();
let id = await driver.installAddon(xpiPath);
Uninstalling an addon requires knowing its id. The id can be obtained from the return value when installing the add-on.
driver.uninstallExtension(id);
driver.uninstall_addon(id)
driver.uninstall_addon(extension_id)
const xpiPath = path.resolve('./test/resources/extensions/selenium-example.xpi')
let driver = await env.builder().build();
let id = await driver.installAddon(xpiPath);
await driver.uninstallAddon(id);
When working with an unfinished or unpublished extension, it will likely not be signed. As such, it can only be installed as “temporary.” This can be done by passing in either a zip file or a directory, here’s an example with a directory:
driver.installExtension(path, true);
driver.install_addon(addon_path, temporary=True)
driver.InstallAddOnFromDirectory(Path.GetFullPath(extensionDirPath), true);
The following examples are for local webdrivers. For remote webdrivers, please refer to the Remote WebDriver page.
The following examples are for local webdrivers. For remote webdrivers, please refer to the Remote WebDriver page.
As of June 2022, Selenium officially no longer supports standalone Internet Explorer. The Internet Explorer driver still supports running Microsoft Edge in “IE Compatibility Mode.”
The IE Driver is the only driver maintained by the Selenium Project directly. While binaries for both the 32-bit and 64-bit versions of Internet Explorer are available, there are some known limitations with the 64-bit driver. As such it is recommended to use the 32-bit driver.
Additional information about using Internet Explorer can be found on the IE Driver Server page
Starting a Microsoft Edge browser in Internet Explorer Compatibility mode with basic defined options looks like this:
InternetExplorerOptions options = new InternetExplorerOptions();
options.attachToEdgeChrome();
options.withEdgeExecutablePath(getEdgeLocation());
driver = new InternetExplorerDriver(options);
options = webdriver.IeOptions()
options.attach_to_edge_chrome = True
options.edge_executable_path = EDGE_LOCATION
driver = webdriver.Ie(options=options)
var options = new InternetExplorerOptions();
options.AttachToEdgeChrome = true;
options.EdgeExecutablePath = GetEdgeLocation();
driver = new InternetExplorerDriver(options);
it 'basic options Win10' do
options = Selenium::WebDriver::Options.ie
options.attach_to_edge_chrome = true
As of Internet Explorer Driver v4.5.0:
So, if IE is not on the system, you only need:
InternetExplorerOptions options = new InternetExplorerOptions();
driver = new InternetExplorerDriver(options);
options = webdriver.IeOptions()
driver = webdriver.Ie(options=options)
var options = new InternetExplorerOptions();
driver = new InternetExplorerDriver(options);
it 'basic options Win11' do
let driver = await new Builder()
.forBrowser('internet explorer')
.setIEOptions(options)
.build();
<p><a href=/documentation/about/contributing/#moving-examples>
<span class="selenium-badge-code" data-bs-toggle="tooltip" data-bs-placement="right"
title="One or more of these examples need to be implemented in the examples directory; click for details in the contribution guide">Move Code</span></a></p>
val options = InternetExplorerOptions()
val driver = InternetExplorerDriver(options)
Here are a few common use cases with different capabilities:
在某些环境中, 当打开文件上传对话框时, Internet Explorer可能会超时. IEDriver的默认超时为1000毫秒, 但您可以使用fileUploadDialogTimeout功能来增加超时时间.
InternetExplorerOptions options = new InternetExplorerOptions();
options.waitForUploadDialogUpTo(Duration.ofSeconds(2));
WebDriver driver = new RemoteWebDriver(options);
from selenium import webdriver
options = webdriver.IeOptions()
options.file_upload_dialog_timeout = 2000
driver = webdriver.Ie(options=options)
driver.get("http://www.google.com")
driver.quit()
var options = new InternetExplorerOptions();
options.FileUploadDialogTimeout = TimeSpan.FromMilliseconds(2000);
var driver = new RemoteWebDriver(options);
options = Selenium::WebDriver::IE::Options.new
options.file_upload_dialog_timeout = 2000
driver = Selenium::WebDriver.for(:ie, options: options)
const ie = require('selenium-webdriver/ie');
let options = new ie.Options().fileUploadDialogTimeout(2000);
let driver = await Builder()
.setIeOptions(options)
.build();
val options = InternetExplorerOptions()
options.waitForUploadDialogUpTo(Duration.ofSeconds(2))
val driver = RemoteWebDriver(options)
设置为 true
时,
此功能将清除InternetExplorer所有正在运行实例的
缓存, 浏览器历史记录和Cookies
(包括手动启动或由驱动程序启动的实例) .
默认情况下,此设置为 false
.
使用此功能将导致启动浏览器时性能下降, 因为驱动程序将等待直到缓存清除后再启动IE浏览器.
此功能接受一个布尔值作为参数.
InternetExplorerOptions options = new InternetExplorerOptions();
options.destructivelyEnsureCleanSession();
WebDriver driver = new RemoteWebDriver(options);
from selenium import webdriver
options = webdriver.IeOptions()
options.ensure_clean_session = True
driver = webdriver.Ie(options=options)
driver.get("http://www.google.com")
driver.quit()
var options = new InternetExplorerOptions();
options.EnsureCleanSession = true;
var driver = new RemoteWebDriver(options);
options = Selenium::WebDriver::IE::Options.new
options.ensure_clean_session = true
driver = Selenium::WebDriver.for(:ie, options: options)
const ie = require('selenium-webdriver/ie');
let options = new ie.Options().ensureCleanSession(true);
let driver = await Builder()
.setIeOptions(options)
.build();
val options = InternetExplorerOptions()
options.destructivelyEnsureCleanSession()
val driver = RemoteWebDriver(options)
InternetExplorer驱动程序期望浏览器的缩放级别为100%, 否则驱动程序将可能抛出异常. 通过将 ignoreZoomSetting 设置为 true, 可以禁用此默认行为.
此功能接受一个布尔值作为参数.
InternetExplorerOptions options = new InternetExplorerOptions();
options.ignoreZoomSettings();
WebDriver driver = new RemoteWebDriver(options);
from selenium import webdriver
options = webdriver.IeOptions()
options.ignore_zoom_level = True
driver = webdriver.Ie(options=options)
driver.get("http://www.google.com")
driver.quit()
var options = new InternetExplorerOptions();
options.IgnoreZoomLevel = true;
var driver = new RemoteWebDriver(options);
options = Selenium::WebDriver::IE::Options.new
options.ignore_zoom_level = true
driver = Selenium::WebDriver.for(:ie, options: options)
const ie = require('selenium-webdriver/ie');
let options = new ie.Options().ignoreZoomSetting(true);
let driver = await Builder()
.setIeOptions(options)
.build();
val options = InternetExplorerOptions()
options.ignoreZoomSettings()
val driver = RemoteWebDriver(options)
启动新的IE会话时是否跳过 保护模式 检查.
如果未设置, 并且所有区域的 保护模式 设置都不同, 则驱动程序将可能引发异常.
如果将功能设置为 true
,
则测试可能会变得不稳定, 无响应, 或者浏览器可能会挂起.
但是, 到目前为止,
这仍然是第二好的选择,
并且第一选择应该 始终 是手动实际设置每个区域的保护模式设置.
如果用户正在使用此属性,
则只会给予 “尽力而为” 的支持.
此功能接受一个布尔值作为参数.
InternetExplorerOptions options = new InternetExplorerOptions();
options.introduceFlakinessByIgnoringSecurityDomains();
WebDriver driver = new RemoteWebDriver(options);
from selenium import webdriver
options = webdriver.IeOptions()
options.ignore_protected_mode_settings = True
driver = webdriver.Ie(options=options)
driver.get("http://www.google.com")
driver.quit()
var options = new InternetExplorerOptions();
options.IntroduceInstabilityByIgnoringProtectedModeSettings = true;
var driver = new RemoteWebDriver(options);
options = Selenium::WebDriver::IE::Options.new
options.ignore_protected_mode_settings = true
driver = Selenium::WebDriver.for(:ie, options: options)
const ie = require('selenium-webdriver/ie');
let options = new ie.Options().introduceFlakinessByIgnoringProtectedModeSettings(true);
let driver = await Builder()
.setIeOptions(options)
.build();
val options = InternetExplorerOptions()
options.introduceFlakinessByIgnoringSecurityDomains()
val driver = RemoteWebDriver(options)
设置为 true
时,
此功能将禁止IEDriverServer的诊断输出.
此功能接受一个布尔值作为参数.
InternetExplorerOptions options = new InternetExplorerOptions();
options.setCapability("silent", true);
WebDriver driver = new InternetExplorerDriver(options);
from selenium import webdriver
options = webdriver.IeOptions()
options.set_capability("silent", True)
driver = webdriver.Ie(options=options)
driver.get("http://www.google.com")
driver.quit()
InternetExplorerOptions options = new InternetExplorerOptions();
options.AddAdditionalInternetExplorerOption("silent", true);
IWebDriver driver = new InternetExplorerDriver(options);
<p><a href=/documentation/about/contributing/#creating-examples>
<span class="selenium-badge-code" data-bs-toggle="tooltip" data-bs-placement="right"
title="This code example is missing. Examples are added to the examples directory; click for details in the contribution guide">Add Example</span></a></p>
const {Builder,By, Capabilities} = require('selenium-webdriver');
let caps = Capabilities.ie();
caps.set('silent', true);
(async function example() {
let driver = await new Builder()
.forBrowser('internet explorer')
.withCapabilities(caps)
.build();
try {
await driver.get('http://www.google.com/ncr');
}
finally {
await driver.quit();
}
})();
import org.openqa.selenium.Capabilities
import org.openqa.selenium.ie.InternetExplorerDriver
import org.openqa.selenium.ie.InternetExplorerOptions
fun main() {
val options = InternetExplorerOptions()
options.setCapability("silent", true)
val driver = InternetExplorerDriver(options)
try {
driver.get("https://google.com/ncr")
val caps = driver.getCapabilities()
println(caps)
} finally {
driver.quit()
}
}
Internet Explorer包含几个命令行选项, 使您可以进行故障排除和配置浏览器.
下面介绍了一些受支持的命令行选项
-private : 用于在私有浏览模式下启动IE. 这适用于IE 8和更高版本.
-k : 在kiosk模式下启动Internet Explorer. 浏览器在一个最大化的窗口中打开, 该窗口不显示地址栏, 导航按钮或状态栏.
-extoff : 在无附加模式下启动IE. 此选项专门用于解决浏览器加载项问题. 在IE 7和更高版本中均可使用.
注意: forceCreateProcessApi 应该启用命令行参数才能正常工作.
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.ie.InternetExplorerOptions;
public class ieTest {
public static void main(String[] args) {
InternetExplorerOptions options = new InternetExplorerOptions();
options.useCreateProcessApiToLaunchIe();
options.addCommandSwitches("-k");
InternetExplorerDriver driver = new InternetExplorerDriver(options);
try {
driver.get("https://google.com/ncr");
Capabilities caps = driver.getCapabilities();
System.out.println(caps);
} finally {
driver.quit();
}
}
}
from selenium import webdriver
options = webdriver.IeOptions()
options.add_argument('-private')
options.force_create_process_api = True
driver = webdriver.Ie(options=options)
driver.get("http://www.google.com")
driver.quit()
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.IE;
namespace ieTest {
class Program {
static void Main(string[] args) {
InternetExplorerOptions options = new InternetExplorerOptions();
options.ForceCreateProcessApi = true;
options.BrowserCommandLineArguments = "-k";
IWebDriver driver = new InternetExplorerDriver(options);
driver.Url = "https://google.com/ncr";
}
}
}
require 'selenium-webdriver'
options = Selenium::WebDriver::IE::Options.new
options.force_create_process_api = true
options.add_argument('-k')
driver = Selenium::WebDriver.for(:ie, options: options)
begin
driver.get 'https://google.com'
puts(driver.capabilities.to_json)
ensure
driver.quit
end
const ie = require('selenium-webdriver/ie');
let options = new ie.Options();
options.addBrowserCommandSwitches('-k');
options.addBrowserCommandSwitches('-private');
options.forceCreateProcessApi(true);
driver = await env.builder()
.setIeOptions(options)
.build();
import org.openqa.selenium.Capabilities
import org.openqa.selenium.ie.InternetExplorerDriver
import org.openqa.selenium.ie.InternetExplorerOptions
fun main() {
val options = InternetExplorerOptions()
options.useCreateProcessApiToLaunchIe()
options.addCommandSwitches("-k")
val driver = InternetExplorerDriver(options)
try {
driver.get("https://google.com/ncr")
val caps = driver.getCapabilities()
println(caps)
} finally {
driver.quit()
}
}
强制使用CreateProcess API启动Internet Explorer. 默认值为false.
对于IE 8及更高版本, 此选项要求将 “TabProcGrowth” 注册表值设置为0.
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.ie.InternetExplorerOptions;
public class ieTest {
public static void main(String[] args) {
InternetExplorerOptions options = new InternetExplorerOptions();
options.useCreateProcessApiToLaunchIe();
InternetExplorerDriver driver = new InternetExplorerDriver(options);
try {
driver.get("https://google.com/ncr");
Capabilities caps = driver.getCapabilities();
System.out.println(caps);
} finally {
driver.quit();
}
}
}
from selenium import webdriver
options = webdriver.IeOptions()
options.force_create_process_api = True
driver = webdriver.Ie(options=options)
driver.get("http://www.google.com")
driver.quit()
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.IE;
namespace ieTest {
class Program {
static void Main(string[] args) {
InternetExplorerOptions options = new InternetExplorerOptions();
options.ForceCreateProcessApi = true;
IWebDriver driver = new InternetExplorerDriver(options);
driver.Url = "https://google.com/ncr";
}
}
}
require 'selenium-webdriver'
options = Selenium::WebDriver::IE::Options.new
options.force_create_process_api = true
driver = Selenium::WebDriver.for(:ie, options: options)
begin
driver.get 'https://google.com'
puts(driver.capabilities.to_json)
ensure
driver.quit
end
const ie = require('selenium-webdriver/ie');
let options = new ie.Options();
options.forceCreateProcessApi(true);
driver = await env.builder()
.setIeOptions(options)
.build();
import org.openqa.selenium.Capabilities
import org.openqa.selenium.ie.InternetExplorerDriver
import org.openqa.selenium.ie.InternetExplorerOptions
fun main() {
val options = InternetExplorerOptions()
options.useCreateProcessApiToLaunchIe()
val driver = InternetExplorerDriver(options)
try {
driver.get("https://google.com/ncr")
val caps = driver.getCapabilities()
println(caps)
} finally {
driver.quit()
}
}
Service settings common to all browsers are described on the Service page.
Getting driver logs can be helpful for debugging various issues. The Service class lets you direct where the logs will go. Logging output is ignored unless the user directs it somewhere.
To change the logging output to save to a specific file:
.withLogFile(getLogLocation())
Note: Java also allows setting file output by System Property:
Property key: InternetExplorerDriverService.IE_DRIVER_LOGFILE_PROPERTY
Property value: String representing path to log file
def test_log_to_file(log_path):
To change the logging output to display in the console as STDOUT:
.withLogOutput(System.out)
Note: Java also allows setting console output by System Property;
Property key: InternetExplorerDriverService.IE_DRIVER_LOGFILE_PROPERTY
Property value: DriverService.LOG_STDOUT
or DriverService.LOG_STDERR
There are 6 available log levels: FATAL
, ERROR
, WARN
, INFO
, DEBUG
, and TRACE
If logging output is specified, the default level is FATAL
.withLogLevel(InternetExplorerDriverLogLevel.WARN)
Note: Java also allows setting log level by System Property:
Property key: InternetExplorerDriverService.IE_DRIVER_LOGLEVEL_PROPERTY
Property value: String representation of InternetExplorerDriverLogLevel.DEBUG.toString()
enum
@pytest.mark.skipif(sys.platform != "win32", reason="requires Windows")
service.LoggingLevel = InternetExplorerDriverLogLevel.Warn;
.withExtractPath(getTempDirectory())
service.LibraryExtractionPath = GetTempDirectory();
与Chromium和Firefox驱动不同, safari驱动随操作系统安装. 要在 Safari 上启用自动化, 请从终端运行以下命令:
safaridriver --enable
所有浏览器通用的Capabilities在选项页.
Safari独有的Capabilities可以在Apple的页面关于Safari的WebDriver 上找到
使用基本定义的选项启动 Safari 会话如下所示:
SafariOptions options = new SafariOptions();
driver = new SafariDriver(options);
options = webdriver.SafariOptions()
driver = webdriver.Safari(options=options)
var options = new SafariOptions();
driver = new SafariDriver(options);
options = Selenium::WebDriver::Options.safari
@driver = Selenium::WebDriver.for :safari, options: options
let driver = await env.builder()
.setSafariOptions(options)
.build();
val options = SafariOptions()
val driver = SafariDriver(options)
那些希望在iOS上自动化Safari的人可以参考 Appium project.
Service settings common to all browsers are described on the Service page.
Unlike other browsers, Safari doesn’t let you choose where logs are output, or change levels. The one option
available is to turn logs off or on. If logs are toggled on, they can be found at:~/Library/Logs/com.apple.WebDriver/
.
.withLogging(true)
Note: Java also allows setting console output by System Property;
Property key: SafariDriverService.SAFARI_DRIVER_LOGGING
Property value: "true"
or "false"
service = webdriver.SafariService(service_args=["--diagnose"])
Apple provides a development version of their browser — Safari Technology Preview To use this version in your code:
Perhaps the most common challenge for browser automation is ensuring that the web application is in a state to execute a particular Selenium command as desired. The processes often end up in a race condition where sometimes the browser gets into the right state first (things work as intended) and sometimes the Selenium code executes first (things do not work as intended). This is one of the primary causes of flaky tests.
All navigation commands wait for a specific readyState
value
based on the page load strategy (the
default value to wait for is "complete"
) before the driver returns control to the code.
The readyState
only concerns itself with loading assets defined in the HTML,
but loaded JavaScript assets often result in changes to the site,
and elements that need to be interacted with may not yet be on the page
when the code is ready to execute the next Selenium command.
Similarly, in a lot of single page applications, elements get dynamically added to a page or change visibility based on a click. An element must be both present and displayed on the page in order for Selenium to interact with it.
Take this page for example: https://www.selenium.dev/selenium/web/dynamic.html When the “Add a box!” button is clicked, a “div” element that does not exist is created. When the “Reveal a new input” button is clicked, a hidden text field element is displayed. In both cases the transition takes a couple seconds. If the Selenium code is to click one of these buttons and interact with the resulting element, it will do so before that element is ready and fail.
The first solution many people turn to is adding a sleep statement to pause the code execution for a set period of time. Because the code can’t know exactly how long it needs to wait, this can fail when it doesn’t sleep long enough. Alternately, if the value is set too high and a sleep statement is added in every place it is needed, the duration of the session can become prohibitive.
Selenium provides two different mechanisms for synchronization that are better.
Selenium has a built-in way to automatically wait for elements called an implicit wait. An implicit wait value can be set either with the timeouts capability in the browser options, or with a driver method (as shown below).
This is a global setting that applies to every element location call for the entire session.
The default value is 0
, which means that if the element is not found, it will
immediately return an error. If an implicit wait is set, the driver will wait for the
duration of the provided value before returning the error. Note that as soon as the
element is located, the driver will return the element reference and the code will continue executing,
so a larger implicit wait value won’t necessarily increase the duration of the session.
Warning: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example, setting an implicit wait of 10 seconds and an explicit wait of 15 seconds could cause a timeout to occur after 20 seconds.
Solving our example with an implicit wait looks like this:
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(2));
driver.get("https://www.selenium.dev/selenium/web/dynamic.html");
driver.findElement(By.id("adder")).click();
WebElement added = driver.findElement(By.id("box0"));
driver.implicitly_wait(2)
driver.get('https://www.selenium.dev/selenium/web/dynamic.html')
driver.find_element(By.ID, "adder").click()
added = driver.find_element(By.ID, "box0")
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(2);
driver.Url = "https://www.selenium.dev/selenium/web/dynamic.html";
driver.FindElement(By.Id("adder")).Click();
IWebElement added = driver.FindElement(By.Id("box0"));
driver.manage.timeouts.implicit_wait = 2
driver.get 'https://www.selenium.dev/selenium/web/dynamic.html'
driver.find_element(id: 'adder').click
added = driver.find_element(id: 'box0')
await driver.manage().setTimeouts({ implicit: 2000 });
await driver.get('https://www.selenium.dev/selenium/web/dynamic.html');
await driver.findElement(By.id("adder")).click();
let added = await driver.findElement(By.id("box0"));
Explicit waits are loops added to the code that poll the application for a specific condition to evaluate as true before it exits the loop and continues to the next command in the code. If the condition is not met before a designated timeout value, the code will give a timeout error. Since there are many ways for the application not to be in the desired state, so explicit waits are a great choice to specify the exact condition to wait for in each place it is needed. Another nice feature is that, by default, the Selenium Wait class automatically waits for the designated element to exist.
This example shows the condition being waited for as a lambda. Java also supports Expected Conditions
WebElement revealed = driver.findElement(By.id("revealed"));
Wait<WebDriver> wait = new WebDriverWait(driver, Duration.ofSeconds(2));
driver.findElement(By.id("reveal")).click();
wait.until(d -> revealed.isDisplayed());
revealed.sendKeys("Displayed");
This example shows the condition being waited for as a lambda. Python also supports Expected Conditions
revealed = driver.find_element(By.ID, "revealed")
wait = WebDriverWait(driver, timeout=2)
driver.find_element(By.ID, "reveal").click()
wait.until(lambda d : revealed.is_displayed())
revealed.send_keys("Displayed")
IWebElement revealed = driver.FindElement(By.Id("revealed"));
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(2));
driver.FindElement(By.Id("reveal")).Click();
wait.Until(d => revealed.Displayed);
revealed.SendKeys("Displayed");
revealed = driver.find_element(id: 'revealed')
wait = Selenium::WebDriver::Wait.new
driver.find_element(id: 'reveal').click
wait.until { revealed.displayed? }
revealed.send_keys('Displayed')
JavaScript also supports Expected Conditions
await driver.get('https://www.selenium.dev/selenium/web/dynamic.html');
let revealed = await driver.findElement(By.id("revealed"));
await driver.findElement(By.id("reveal")).click();
await driver.wait(until.elementIsVisible(revealed), 2000);
await revealed.sendKeys("Displayed");
The Wait class can be instantiated with various parameters that will change how the conditions are evaluated.
This can include:
For instance, if the element not interactable error is retried by default, then we can
add an action on a method inside the code getting executed (we just need to
make sure that the code returns true
when it is successful):
The easiest way to customize Waits in Java is to use the FluentWait
class:
WebElement revealed = driver.findElement(By.id("revealed"));
Wait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(2))
.pollingEvery(Duration.ofMillis(300))
.ignoring(ElementNotInteractableException.class);
driver.findElement(By.id("reveal")).click();
wait.until(d -> {
revealed.sendKeys("Displayed");
return true;
});
revealed = driver.find_element(By.ID, "revealed")
errors = [NoSuchElementException, ElementNotInteractableException]
wait = WebDriverWait(driver, timeout=2, poll_frequency=.2, ignored_exceptions=errors)
driver.find_element(By.ID, "reveal").click()
wait.until(lambda d : revealed.send_keys("Displayed") or True)
IWebElement revealed = driver.FindElement(By.Id("revealed"));
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(2))
{
PollingInterval = TimeSpan.FromMilliseconds(300),
};
wait.IgnoreExceptionTypes(typeof(ElementNotInteractableException));
driver.FindElement(By.Id("reveal")).Click();
wait.Until(d => {
revealed.SendKeys("Displayed");
return true;
});
revealed = driver.find_element(id: 'revealed')
errors = [Selenium::WebDriver::Error::NoSuchElementError,
Selenium::WebDriver::Error::ElementNotInteractableError]
wait = Selenium::WebDriver::Wait.new(timeout: 2,
interval: 0.3,
ignore: errors)
driver.find_element(id: 'reveal').click
wait.until { revealed.send_keys('Displayed') || true }
大多数人的Selenium代码都涉及使用web元素.
当input元素为文件类型时, 文件上传对话框可以使用Selenium处理. 例如, 在这个网页中可以发现- https://the-internet.herokuapp.com/upload 我们需要一个可用的文件, 用于上传. 不同语言的文件上传的代码实现如下 -
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
class fileUploadDoc{
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://the-internet.herokuapp.com/upload");
//we want to import selenium-snapshot file.
driver.findElement(By.id("file-upload")).sendKeys("selenium-snapshot.jpg");
driver.findElement(By.id("file-submit")).submit();
if(driver.getPageSource().contains("File Uploaded!")) {
System.out.println("file uploaded");
}
else{
System.out.println("file not uploaded");
}
driver.quit();
}
}
from selenium import webdriver
driver.implicitly_wait(10)
driver.get("https://the-internet.herokuapp.com/upload");
driver.find_element(By.ID,"file-upload").send_keys("selenium-snapshot.jpg")
driver.find_element(By.ID,"file-submit").submit()
if(driver.page_source.find("File Uploaded!")):
print("file upload success")
else:
print("file upload not successful")
driver.quit()
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace SeleniumDocumentation.SeleniumPRs
{
class FileUploadExample
{
static void Main(String[] args)
{
IWebDriver driver = new ChromeDriver();
try
{
// Navigate to Url
driver.Navigate().GoToUrl("https://the-internet.herokuapp.com/upload");
driver.FindElement(By.Id("file-upload")).SendKeys("selenium-snapshot.jpg");
driver.FindElement(By.Id("file-submit")).Submit();
if (driver.PageSource.Contains("File Uploaded!"))
{
Console.WriteLine("file uploaded");
}
else
{
Console.WriteLine("file not uploaded");
}
driver.Quit();
}
}
}
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
driver.get("https://the-internet.herokuapp.com/upload")
driver.find_element(:id,"file-upload").send_keys("selenium-snapshot.jpg")
driver.find_element(:id,"file-submit").submit()
if driver.page_source().include? "File Uploaded!"
puts "file upload success"
else
puts "file upload not successful"
end
await driver.get('https://www.selenium.dev/selenium/web/upload.html');
// Upload snapshot
await driver.findElement(By.id("upload")).sendKeys(image);
await driver.findElement(By.id("go")).submit();
import org.openqa.selenium.By
import org.openqa.selenium.chrome.ChromeDriver
fun main() {
val driver = ChromeDriver()
driver.get("https://the-internet.herokuapp.com/upload")
driver.findElement(By.id("file-upload")).sendKeys("selenium-snapshot.jpg")
driver.findElement(By.id("file-submit")).submit()
if(driver.pageSource.contains("File Uploaded!")) {
println("file uploaded")
}
else{
println("file not uploaded")
}
}
所以上面的示例代码有助于我们理解 如何使用Selenium上传文件.
One of the most fundamental aspects of using Selenium is obtaining element references to work with. Selenium offers a number of built-in locator strategies to uniquely identify an element. There are many ways to use the locators in very advanced scenarios. For the purposes of this documentation, let’s consider this HTML snippet:
<ol id="vegetables">
<li class="potatoes">…
<li class="onions">…
<li class="tomatoes"><span>Tomato is a Vegetable</span>…
</ol>
<ul id="fruits">
<li class="bananas">…
<li class="apples">…
<li class="tomatoes"><span>Tomato is a Fruit</span>…
</ul>
Many locators will match multiple elements on the page. The singular find element method will return a reference to the first element found within a given context.
When the find element method is called on the driver instance, it returns a reference to the first element in the DOM that matches with the provided locator. This value can be stored and used for future element actions. In our example HTML above, there are two elements that have a class name of “tomatoes” so this method will return the element in the “vegetables” list.
WebElement vegetable = driver.findElement(By.className("tomatoes"));
vegetable = driver.find_element(By.CLASS_NAME, "tomatoes")
var vegetable = driver.FindElement(By.ClassName("tomatoes"));
vegetable = driver.find_element(class: 'tomatoes')
const vegetable = await driver.findElement(By.className('tomatoes'));
val vegetable: WebElement = driver.findElement(By.className("tomatoes"))
Rather than finding a unique locator in the entire DOM, it is often useful to narrow the search to the scope of another located element. In the above example there are two elements with a class name of “tomatoes” and it is a little more challenging to get the reference for the second one.
One solution is to locate an element with a unique attribute that is an ancestor of the desired element and not an ancestor of the undesired element, then call find element on that object:
WebElement fruits = driver.findElement(By.id("fruits"));
WebElement fruit = fruits.findElement(By.className("tomatoes"));
fruits = driver.find_element(By.ID, "fruits")
fruit = fruits.find_element(By.CLASS_NAME,"tomatoes")
IWebElement fruits = driver.FindElement(By.Id("fruits"));
IWebElement fruit = fruits.FindElement(By.ClassName("tomatoes"));
fruits = driver.find_element(id: 'fruits')
fruit = fruits.find_element(class: 'tomatoes')
const fruits = await driver.findElement(By.id('fruits'));
const fruit = fruits.findElement(By.className('tomatoes'));
val fruits = driver.findElement(By.id("fruits"))
val fruit = fruits.findElement(By.className("tomatoes"))
Java and C#WebDriver
, WebElement
and ShadowRoot
classes all implement a SearchContext
interface, which is
considered a role-based interface. Role-based interfaces allow you to determine whether a particular
driver implementation supports a given feature. These interfaces are clearly defined and try
to adhere to having only a single role of responsibility.
A nested lookup might not be the most effective location strategy since it requires two separate commands to be issued to the browser.
To improve the performance slightly, we can use either CSS or XPath to find this element in a single command. See the Locator strategy suggestions in our Encouraged test practices section.
For this example, we’ll use a CSS Selector:
WebElement fruit = driver.findElement(By.cssSelector("#fruits .tomatoes"));
fruit = driver.find_element(By.CSS_SELECTOR,"#fruits .tomatoes")
var fruit = driver.FindElement(By.CssSelector("#fruits .tomatoes"));
fruit = driver.find_element(css: '#fruits .tomatoes')
const fruit = await driver.findElement(By.css('#fruits .tomatoes'));
val fruit = driver.findElement(By.cssSelector("#fruits .tomatoes"))
There are several use cases for needing to get references to all elements that match a locator, rather than just the first one. The plural find elements methods return a collection of element references. If there are no matches, an empty list is returned. In this case, references to all fruits and vegetable list items will be returned in a collection.
List<WebElement> plants = driver.findElements(By.tagName("li"));
plants = driver.find_elements(By.TAG_NAME, "li")
IReadOnlyList<IWebElement> plants = driver.FindElements(By.TagName("li"));
plants = driver.find_elements(tag_name: 'li')
const plants = await driver.findElements(By.tagName('li'));
val plants: List<WebElement> = driver.findElements(By.tagName("li"))
Often you get a collection of elements but want to work with a specific element, which means you need to iterate over the collection and identify the one you want.
List<WebElement> elements = driver.findElements(By.tagName("li"));
for (WebElement element : elements) {
System.out.println("Paragraph text:" + element.getText());
}
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Firefox()
# Navigate to Url
driver.get("https://www.example.com")
# Get all the elements available with tag name 'p'
elements = driver.find_elements(By.TAG_NAME, 'p')
for e in elements:
print(e.text)
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using System.Collections.Generic;
namespace FindElementsExample {
class FindElementsExample {
public static void Main(string[] args) {
IWebDriver driver = new FirefoxDriver();
try {
// Navigate to Url
driver.Navigate().GoToUrl("https://example.com");
// Get all the elements available with tag name 'p'
IList < IWebElement > elements = driver.FindElements(By.TagName("p"));
foreach(IWebElement e in elements) {
System.Console.WriteLine(e.Text);
}
} finally {
driver.Quit();
}
}
}
}
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :firefox
begin
# Navigate to URL
driver.get 'https://www.example.com'
# Get all the elements available with tag name 'p'
elements = driver.find_elements(:tag_name,'p')
elements.each { |e|
puts e.text
}
ensure
driver.quit
end
const {Builder, By} = require('selenium-webdriver');
(async function example() {
let driver = await new Builder().forBrowser('firefox').build();
try {
// Navigate to Url
await driver.get('https://www.example.com');
// Get all the elements available with tag 'p'
let elements = await driver.findElements(By.css('p'));
for(let e of elements) {
console.log(await e.getText());
}
}
finally {
await driver.quit();
}
})();
import org.openqa.selenium.By
import org.openqa.selenium.firefox.FirefoxDriver
fun main() {
val driver = FirefoxDriver()
try {
driver.get("https://example.com")
// Get all the elements available with tag name 'p'
val elements = driver.findElements(By.tagName("p"))
for (element in elements) {
println("Paragraph text:" + element.text)
}
} finally {
driver.quit()
}
}
It is used to find the list of matching child WebElements within the context of parent element. To achieve this, the parent WebElement is chained with ‘findElements’ to access child elements
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.List;
public class findElementsFromElement {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("https://example.com");
// Get element with tag name 'div'
WebElement element = driver.findElement(By.tagName("div"));
// Get all the elements available with tag name 'p'
List<WebElement> elements = element.findElements(By.tagName("p"));
for (WebElement e : elements) {
System.out.println(e.getText());
}
} finally {
driver.quit();
}
}
}
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://www.example.com")
# Get element with tag name 'div'
element = driver.find_element(By.TAG_NAME, 'div')
# Get all the elements available with tag name 'p'
elements = element.find_elements(By.TAG_NAME, 'p')
for e in elements:
print(e.text)
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System.Collections.Generic;
namespace FindElementsFromElement {
class FindElementsFromElement {
public static void Main(string[] args) {
IWebDriver driver = new ChromeDriver();
try {
driver.Navigate().GoToUrl("https://example.com");
// Get element with tag name 'div'
IWebElement element = driver.FindElement(By.TagName("div"));
// Get all the elements available with tag name 'p'
IList < IWebElement > elements = element.FindElements(By.TagName("p"));
foreach(IWebElement e in elements) {
System.Console.WriteLine(e.Text);
}
} finally {
driver.Quit();
}
}
}
}
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
# Navigate to URL
driver.get 'https://www.example.com'
# Get element with tag name 'div'
element = driver.find_element(:tag_name,'div')
# Get all the elements available with tag name 'p'
elements = element.find_elements(:tag_name,'p')
elements.each { |e|
puts e.text
}
ensure
driver.quit
end
const {Builder, By} = require('selenium-webdriver');
(async function example() {
let driver = new Builder()
.forBrowser('chrome')
.build();
await driver.get('https://www.example.com');
// Get element with tag name 'div'
let element = driver.findElement(By.css("div"));
// Get all the elements available with tag name 'p'
let elements = await element.findElements(By.css("p"));
for(let e of elements) {
console.log(await e.getText());
}
})();
import org.openqa.selenium.By
import org.openqa.selenium.chrome.ChromeDriver
fun main() {
val driver = ChromeDriver()
try {
driver.get("https://example.com")
// Get element with tag name 'div'
val element = driver.findElement(By.tagName("div"))
// Get all the elements available with tag name 'p'
val elements = element.findElements(By.tagName("p"))
for (e in elements) {
println(e.text)
}
} finally {
driver.quit()
}
}
It is used to track (or) find DOM element which has the focus in the current browsing context.
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
public class activeElementTest {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("http://www.google.com");
driver.findElement(By.cssSelector("[name='q']")).sendKeys("webElement");
// Get attribute of current active element
String attr = driver.switchTo().activeElement().getAttribute("title");
System.out.println(attr);
} finally {
driver.quit();
}
}
}
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://www.google.com")
driver.find_element(By.CSS_SELECTOR, '[name="q"]').send_keys("webElement")
# Get attribute of current active element
attr = driver.switch_to.active_element.get_attribute("title")
print(attr)
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace ActiveElement {
class ActiveElement {
public static void Main(string[] args) {
IWebDriver driver = new ChromeDriver();
try {
// Navigate to Url
driver.Navigate().GoToUrl("https://www.google.com");
driver.FindElement(By.CssSelector("[name='q']")).SendKeys("webElement");
// Get attribute of current active element
string attr = driver.SwitchTo().ActiveElement().GetAttribute("title");
System.Console.WriteLine(attr);
} finally {
driver.Quit();
}
}
}
}
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.get 'https://www.google.com'
driver.find_element(css: '[name="q"]').send_keys('webElement')
# Get attribute of current active element
attr = driver.switch_to.active_element.attribute('title')
puts attr
ensure
driver.quit
end
const {Builder, By} = require('selenium-webdriver');
(async function example() {
let driver = await new Builder().forBrowser('chrome').build();
await driver.get('https://www.google.com');
await driver.findElement(By.css('[name="q"]')).sendKeys("webElement");
// Get attribute of current active element
let attr = await driver.switchTo().activeElement().getAttribute("title");
console.log(`${attr}`)
})();
import org.openqa.selenium.By
import org.openqa.selenium.chrome.ChromeDriver
fun main() {
val driver = ChromeDriver()
try {
driver.get("https://www.google.com")
driver.findElement(By.cssSelector("[name='q']")).sendKeys("webElement")
// Get attribute of current active element
val attr = driver.switchTo().activeElement().getAttribute("title")
print(attr)
} finally {
driver.quit()
}
}
仅有五种基本命令可用于元素的操作:
这些方法的设计目的是尽量模拟用户体验, 所以, 与 Actions接口 不同, 在指定制定操作之前, 会尝试执行两件事.
元素点击命令 执行在 元素中央. 如果元素中央由于某些原因被 遮挡 , Selenium将返回一个 元素点击中断 错误.
// Navigate to Url
driver.get("https://www.selenium.dev/selenium/web/inputs.html");
// Click on the element
driver.findElement(By.name("color_input")).click();
# Navigate to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
# Click on the element
driver.find_element(By.NAME, "color_input").click()
// Navigate to Url
driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/inputs.html");
// Click the element
driver.FindElement(By.Name("color_input")).Click();
# Navigate to URL
driver.get 'https://www.selenium.dev/selenium/web/inputs.html'
# Click the element
driver.find_element(name: 'color_input').click
// Navigate to Url
await driver.get('https://www.selenium.dev/selenium/web/inputs.html');
// Click the element
await driver.findElement(By.name('color_input')).click();
// Navigate to Url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
// Click the element
driver.findElement(By.name("color_input")).click();
元素发送键位命令
将录入提供的键位到 可编辑的 元素.
通常, 这意味着元素是具有 文本
类型的表单的输入元素或具有 内容可编辑
属性的元素.
如果不可编辑, 则返回
无效元素状态 错误.
以下 是WebDriver支持的按键列表.
// Navigate to Url
driver.get("https://www.selenium.dev/selenium/web/inputs.html");
// Clear field to empty it from any previous data
driver.findElement(By.name("email_input")).clear();
//Enter Text
driver.findElement(By.name("email_input")).sendKeys("admin@localhost.dev");
# Navigate to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
# Clear field to empty it from any previous data
driver.find_element(By.NAME, "email_input").clear()
# Enter Text
driver.find_element(By.NAME, "email_input").send_keys("admin@localhost.dev" )
// Navigate to Url
driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/inputs.html");
// Clear field to empty it from any previous data
driver.FindElement(By.Name("email_input")).Clear();
//Enter Text
driver.FindElement(By.Name("email_input")).SendKeys("admin@localhost.dev");
}
# Navigate to URL
driver.get 'https://www.selenium.dev/selenium/web/inputs.html'
# Clear field to empty it from any previous data
driver.find_element(name: 'email_input').clear
# Enter Text
driver.find_element(name: 'email_input').send_keys 'admin@localhost.dev'
// Navigate to Url
await driver.get('https://www.selenium.dev/selenium/web/inputs.html');
//Clear field to empty it from any previous data
await driver.findElement(By.name('email_input')).clear();
// Enter text
await driver.findElement(By.name('email_input')).sendKeys('admin@localhost.dev');
// Navigate to Url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
//Clear field to empty it from any previous data
driver.findElement(By.name("email_input")).clear()
// Enter text
driver.findElement(By.name("email_input")).sendKeys("admin@localhost.dev")
元素清除命令
重置元素的内容.
这要求元素 可编辑,
且 可重置.
通常, 这意味着元素是具有 文本
类型的表单的输入元素或具有 内容可编辑
属性的元素.
如果不满足这些条件, 将返回
无效元素状态 错误.
// Navigate to Url
driver.get("https://www.selenium.dev/selenium/web/inputs.html");
// Clear field to empty it from any previous data
driver.findElement(By.name("email_input")).clear();
# Navigate to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
# Clear field to empty it from any previous data
driver.find_element(By.NAME, "email_input").clear()
// Navigate to Url
driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/inputs.html");
// Clear field to empty it from any previous data
driver.FindElement(By.Name("email_input")).Clear();
}
# Navigate to URL
driver.get 'https://www.selenium.dev/selenium/web/inputs.html'
# Clear field to empty it from any previous data
driver.find_element(name: 'email_input').clear
// Navigate to Url
await driver.get('https://www.selenium.dev/selenium/web/inputs.html');
//Clear field to empty it from any previous data
await driver.findElement(By.name('email_input')).clear();
// Navigate to Url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
//Clear field to empty it from any previous data
driver.findElement(By.name("email_input")).clear()
在Selenium 4中, 不再通过单独的端点以及脚本执行的方法来实现. 因此, 建议不要使用此方法, 而是单击相应的表单提交按钮.
定位器是在页面上标识元素的一种方法。它是传送给 查找元素 方法的参数。
查看 鼓励测试练习 寻找 定位器的小技巧, 包含在查找方法中,不同时间,不同原因下,单独声明的定位器的使用方法。
在 WebDriver 中有 8 种不同的内置元素定位策略:
定位器 Locator | 描述 |
---|---|
class name | 定位class属性与搜索值匹配的元素(不允许使用复合类名) |
css selector | 定位 CSS 选择器匹配的元素 |
id | 定位 id 属性与搜索值匹配的元素 |
name | 定位 name 属性与搜索值匹配的元素 |
link text | 定位link text可视文本与搜索值完全匹配的锚元素 |
partial link text | 定位link text可视文本部分与搜索值部分匹配的锚点元素。如果匹配多个元素,则只选择第一个元素。 |
tag name | 定位标签名称与搜索值匹配的元素 |
xpath | 定位与 XPath 表达式匹配的元素 |
To work on a web element using Selenium, we need to first locate it on the web page. Selenium provides us above mentioned ways, using which we can locate element on the page. To understand and create locator we will use the following HTML snippet.
<html>
<body>
<style>
.information {
background-color: white;
color: black;
padding: 10px;
}
</style>
<h2>Contact Selenium</h2>
<form action="/action_page.php">
<input type="radio" name="gender" value="m" />Male
<input type="radio" name="gender" value="f" />Female <br>
<br>
<label for="fname">First name:</label><br>
<input class="information" type="text" id="fname" name="fname" value="Jane"><br><br>
<label for="lname">Last name:</label><br>
<input class="information" type="text" id="lname" name="lname" value="Doe"><br><br>
<label for="newsletter">Newsletter:</label>
<input type="checkbox" name="newsletter" value="1" /><br><br>
<input type="submit" value="Submit">
</form>
<p>To know more about Selenium, visit the official page
<a href ="www.selenium.dev">Selenium Official Page</a>
</p>
</body>
</html>
The HTML page web element can have attribute class. We can see an example in the above shown HTML snippet. We can identify these elements using the class name locator available in Selenium.
WebDriver driver = new ChromeDriver();
driver.findElement(By.className("information"));
driver = webdriver.Chrome()
driver.find_element(By.CLASS_NAME, "information")
var driver = new ChromeDriver();
driver.FindElement(By.ClassName("information"));
driver = Selenium::WebDriver.for :chrome
driver.find_element(class: 'information')
let driver = await new Builder().forBrowser('chrome').build();
const loc = await driver.findElement(By.className('information'));
val driver = ChromeDriver()
val loc: WebElement = driver.findElement(By.className("information"))
CSS is the language used to style HTML pages. We can use css selector locator strategy to identify the element on the page. If the element has an id, we create the locator as css = #id. Otherwise the format we follow is css =[attribute=value] . Let us see an example from above HTML snippet. We will create locator for First Name textbox, using css.
WebDriver driver = new ChromeDriver();
driver.findElement(By.cssSelector("#fname"));
driver = webdriver.Chrome()
driver.find_element(By.CSS_SELECTOR, "#fname")
var driver = new ChromeDriver();
driver.FindElement(By.CssSelector("#fname"));
driver = Selenium::WebDriver.for :chrome
driver.find_element(css: '#fname')
let driver = await new Builder().forBrowser('chrome').build();
const loc = await driver.findElement(By.css('#fname'));
val driver = ChromeDriver()
val loc: WebElement = driver.findElement(By.css("#fname"))
We can use the ID attribute available with element in a web page to locate it. Generally the ID property should be unique for a element on the web page. We will identify the Last Name field using it.
WebDriver driver = new ChromeDriver();
driver.findElement(By.id("lname"));
driver = webdriver.Chrome()
driver.find_element(By.ID, "lname")
var driver = new ChromeDriver();
driver.FindElement(By.Id("lname"));
driver = Selenium::WebDriver.for :chrome
driver.find_element(id: 'lname')
let driver = await new Builder().forBrowser('chrome').build();
const loc = await driver.findElement(By.id('lname'));
val driver = ChromeDriver()
val loc: WebElement = driver.findElement(By.id("lname"))
We can use the NAME attribute available with element in a web page to locate it. Generally the NAME property should be unique for a element on the web page. We will identify the Newsletter checkbox using it.
WebDriver driver = new ChromeDriver();
driver.findElement(By.name("newsletter"));
driver = webdriver.Chrome()
driver.find_element(By.NAME, "newsletter")
var driver = new ChromeDriver();
driver.FindElement(By.Name("newsletter"));
driver = Selenium::WebDriver.for :chrome
driver.find_element(name: 'newsletter')
let driver = await new Builder().forBrowser('chrome').build();
const loc = await driver.findElement(By.name('newsletter'));
val driver = ChromeDriver()
val loc: WebElement = driver.findElement(By.name("newsletter"))
If the element we want to locate is a link, we can use the link text locator to identify it on the web page. The link text is the text displayed of the link. In the HTML snippet shared, we have a link available, lets see how will we locate it.
WebDriver driver = new ChromeDriver();
driver.findElement(By.linkText("Selenium Official Page"));
driver = webdriver.Chrome()
driver.find_element(By.LINK_TEXT, "Selenium Official Page")
var driver = new ChromeDriver();
driver.FindElement(By.LinkText("Selenium Official Page"));
driver = Selenium::WebDriver.for :chrome
driver.find_element(link_text: 'Selenium Official Page')
let driver = await new Builder().forBrowser('chrome').build();
const loc = await driver.findElement(By.linkText('Selenium Official Page'));
val driver = ChromeDriver()
val loc: WebElement = driver.findElement(By.linkText("Selenium Official Page"))
If the element we want to locate is a link, we can use the partial link text locator to identify it on the web page. The link text is the text displayed of the link. We can pass partial text as value. In the HTML snippet shared, we have a link available, lets see how will we locate it.
WebDriver driver = new ChromeDriver();
driver.findElement(By.partialLinkText("Official Page"));
driver = webdriver.Chrome()
driver.find_element(By.PARTIAL_LINK_TEXT, "Official Page")
var driver = new ChromeDriver();
driver.FindElement(By.PartialLinkText("Official Page"));
driver = Selenium::WebDriver.for :chrome
driver.find_element(partial_link_text: 'Official Page')
let driver = await new Builder().forBrowser('chrome').build();
const loc = await driver.findElement(By.partialLinkText('Official Page'));
val driver = ChromeDriver()
val loc: WebElement = driver.findElement(By.partialLinkText("Official Page"))
We can use the HTML TAG itself as a locator to identify the web element on the page. From the above HTML snippet shared, lets identify the link, using its html tag “a”.
WebDriver driver = new ChromeDriver();
driver.findElement(By.tagName("a"));
driver = webdriver.Chrome()
driver.find_element(By.TAG_NAME, "a")
var driver = new ChromeDriver();
driver.FindElement(By.TagName("a"));
driver = Selenium::WebDriver.for :chrome
driver.find_element(tag_name: 'a')
let driver = await new Builder().forBrowser('chrome').build();
const loc = await driver.findElement(By.tagName('a'));
val driver = ChromeDriver()
val loc: WebElement = driver.findElement(By.tagName("a"))
A HTML document can be considered as a XML document, and then we can use xpath which will be the path traversed to reach the element of interest to locate the element. The XPath could be absolute xpath, which is created from the root of the document. Example - /html/form/input[1]. This will return the male radio button. Or the xpath could be relative. Example- //input[@name=‘fname’]. This will return the first name text box. Let us create locator for female radio button using xpath.
WebDriver driver = new ChromeDriver();
driver.findElement(By.xpath("//input[@value='f']"));
driver = webdriver.Chrome()
driver.find_element(By.XPATH, "//input[@value='f']")
var driver = new ChromeDriver();
driver.FindElement(By.Xpath("//input[@value='f']"));
driver = Selenium::WebDriver.for :chrome
driver.find_element(xpath: '//input[@value='f']')
let driver = await new Builder().forBrowser('chrome').build();
const loc = await driver.findElement(By.xpath('//input[@value='f']'));
val driver = ChromeDriver()
val loc: WebElement = driver.findElement(By.xpath('//input[@value='f']'))
Selenium 4 introduces Relative Locators (previously called as Friendly Locators). These locators are helpful when it is not easy to construct a locator for the desired element, but easy to describe spatially where the element is in relation to an element that does have an easily constructed locator.
Selenium uses the JavaScript function
getBoundingClientRect()
to determine the size and position of elements on the page, and can use this information to locate neighboring elements.
find the relative elements.
Relative locator methods can take as the argument for the point of origin, either a previously located element reference, or another locator. In these examples we’ll be using locators only, but you could swap the locator in the final method with an element object and it will work the same.
Let us consider the below example for understanding the relative locators.
If the email text field element is not easily identifiable for some reason, but the password text field element is, we can locate the text field element using the fact that it is an “input” element “above” the password element.
By emailLocator = RelativeLocator.with(By.tagName("input")).above(By.id("password"));
email_locator = locate_with(By.TAG_NAME, "input").above({By.ID: "password"})
var emailLocator = RelativeBy.WithLocator(By.TagName("input")).Above(By.Id("password"));
email_locator = {relative: {tag_name: 'input', above: {id: 'password'}}}
let emailLocator = locateWith(By.tagName('input')).above(By.id('password'));
val emailLocator = RelativeLocator.with(By.tagName("input")).above(By.id("password"))
If the password text field element is not easily identifiable for some reason, but the email text field element is, we can locate the text field element using the fact that it is an “input” element “below” the email element.
By passwordLocator = RelativeLocator.with(By.tagName("input")).below(By.id("email"));
password_locator = locate_with(By.TAG_NAME, "input").below({By.ID: "email"})
var passwordLocator = RelativeBy.WithLocator(By.TagName("input")).Below(By.Id("email"));
password_locator = {relative: {tag_name: 'input', below: {id: 'email'}}}
let passwordLocator = locateWith(By.tagName('input')).below(By.id('email'));
val passwordLocator = RelativeLocator.with(By.tagName("input")).below(By.id("email"))
If the cancel button is not easily identifiable for some reason, but the submit button element is, we can locate the cancel button element using the fact that it is a “button” element to the “left of” the submit element.
By cancelLocator = RelativeLocator.with(By.tagName("button")).toLeftOf(By.id("submit"));
cancel_locator = locate_with(By.TAG_NAME, "button").to_left_of({By.ID: "submit"})
var cancelLocator = RelativeBy.WithLocator(By.tagName("button")).LeftOf(By.Id("submit"));
cancel_locator = {relative: {tag_name: 'button', left: {id: 'submit'}}}
let cancelLocator = locateWith(By.tagName('button')).toLeftOf(By.id('submit'));
val cancelLocator = RelativeLocator.with(By.tagName("button")).toLeftOf(By.id("submit"))
If the submit button is not easily identifiable for some reason, but the cancel button element is, we can locate the submit button element using the fact that it is a “button” element “to the right of” the cancel element.
By submitLocator = RelativeLocator.with(By.tagName("button")).toRightOf(By.id("cancel"));
submit_locator = locate_with(By.TAG_NAME, "button").to_right_of({By.ID: "cancel"})
var submitLocator = RelativeBy.WithLocator(By.tagName("button")).RightOf(By.Id("cancel"));
submit_locator = {relative: {tag_name: 'button', right: {id: 'cancel'}}}
let submitLocator = locateWith(By.tagName('button')).toRightOf(By.id('cancel'));
val submitLocator = RelativeLocator.with(By.tagName("button")).toRightOf(By.id("cancel"))
If the relative positioning is not obvious, or it varies based on window size, you can use the near method to
identify an element that is at most 50px
away from the provided locator.
One great use case for this is to work with a form element that doesn’t have an easily constructed locator,
but its associated input label element does.
By emailLocator = RelativeLocator.with(By.tagName("input")).near(By.id("lbl-email"));
email_locator = locate_with(By.TAG_NAME, "input").near({By.ID: "lbl-email"})
var emailLocator = RelativeBy.WithLocator(By.tagName("input")).Near(By.Id("lbl-email"));
email_locator = {relative: {tag_name: 'input', near: {id: 'lbl-email'}}}
let emailLocator = locateWith(By.tagName('input')).near(By.id('lbl-email'));
val emailLocator = RelativeLocator.with(By.tagName("input")).near(By.id("lbl-email"));
You can also chain locators if needed. Sometimes the element is most easily identified as being both above/below one element and right/left of another.
By submitLocator = RelativeLocator.with(By.tagName("button")).below(By.id("email")).toRightOf(By.id("cancel"));
submit_locator = locate_with(By.TAG_NAME, "button").below({By.ID: "email"}).to_right_of({By.ID: "cancel"})
var submitLocator = RelativeBy.WithLocator(By.tagName("button")).Below(By.Id("email")).RightOf(By.Id("cancel"));
submit_locator = {relative: {tag_name: 'button', below: {id: 'email'}, right: {id: 'cancel'}}}
let submitLocator = locateWith(By.tagName('button')).below(By.id('email')).toRightOf(By.id('cancel'));
val submitLocator = RelativeLocator.with(By.tagName("button")).below(By.id("email")).toRightOf(By.id("cancel"))
您可以查询有关特定元素的许多详细信息。
此方法用于检查连接的元素是否正确显示在网页上. 返回一个 Boolean
值,
如果连接的元素显示在当前的浏览器上下文中,则为True,否则返回false。
此功能于W3C规范中提及, 但由于无法覆盖所有潜在条件而无法定义。 因此,Selenium不能期望驱动程序直接实现这种功能,现在依赖于直接执行大量JavaScript函数。 这个函数对一个元素的性质和在树中的关系做了许多近似的判断,以返回一个值。
// Navigate to the url
driver.get("https://www.selenium.dev/selenium/web/inputs.html");
// Get boolean value for is element display
boolean isEmailVisible = driver.findElement(By.name("email_input")).isDisplayed();
# Navigate to the url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
# Get boolean value for is element display
is_email_visible = driver.find_element(By.NAME, "email_input").is_displayed()
//Navigate to the url
driver.Url = "https://www.selenium.dev/selenium/web/inputs.html";
//Get boolean value for is element display
Boolean is_email_visible = driver.FindElement(By.Name("email_input")).Displayed;
# Navigate to the url
driver.get("https://www.selenium.dev/selenium/web/inputs.html");
#fetch display status
val = driver.find_element(name: 'email_input').displayed?
// Navigate to url
await driver.get("https://www.selenium.dev/selenium/web/inputs.html");
// Resolves Promise and returns boolean value
let result = await driver.findElement(By.name("email_input")).isDisplayed();
//navigates to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
//returns true if element is displayed else returns false
val flag = driver.findElement(By.name("email_input")).isDisplayed()
此方法用于检查所连接的元素在网页上是启用还是禁用状态。 返回一个布尔值,如果在当前浏览上下文中是 启用 状态,则返回 true,否则返回 false。
//navigates to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html");
//returns true if element is enabled else returns false
boolean value = driver.findElement(By.name("button_input")).isEnabled();
# Navigate to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
# Returns true if element is enabled else returns false
value = driver.find_element(By.NAME, 'button_input').is_enabled()
// Navigate to Url
driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/inputs.html");
// Store the WebElement
IWebElement element = driver.FindElement(By.Name("button_input"));
// Prints true if element is enabled else returns false
System.Console.WriteLine(element.Enabled);
# Navigate to url
driver.get 'https://www.selenium.dev/selenium/web/inputs.html'
# Returns true if element is enabled else returns false
ele = driver.find_element(name: 'button_input').enabled?
// Navigate to url
await driver.get('https://www.selenium.dev/selenium/web/inputs.html');
// Resolves Promise and returns boolean value
let element = await driver.findElement(By.name("button_input")).isEnabled();
//navigates to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
//returns true if element is enabled else returns false
val attr = driver.findElement(By.name("button_input")).isEnabled()
此方法确认相关的元素是否 已选定,常用于复选框、单选框、输入框和选择元素中。
该方法返回一个布尔值,如果在当前浏览上下文中 选择了 引用的元素,则返回 True,否则返回 False。
//navigates to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html");
//returns true if element is checked else returns false
boolean value = driver.findElement(By.name("checkbox_input")).isSelected();
# Navigate to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
# Returns true if element is checked else returns false
value = driver.find_element(By.NAME, "checkbox_input").is_selected()
// Navigate to Url
driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/inputs.html");
// Returns true if element ins checked else returns false
bool value = driver.FindElement(By.Name("checkbox_input")).Selected;
# Navigate to url
driver.get 'https://www.selenium.dev/selenium/web/inputs.html'
# Returns true if element is checked else returns false
ele = driver.find_element(name: "checkbox_input").selected?
// Navigate to url
await driver.get('https://www.selenium.dev/selenium/web/inputs.html');
// Returns true if element ins checked else returns false
let res = await driver.findElement(By.name("checkbox_input")).isSelected();
//navigates to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
//returns true if element is checked else returns false
val attr = driver.findElement(By.name("checkbox_input")).isSelected()
此方法用于获取在当前浏览上下文中具有焦点的被引用元素的TagName。
//navigates to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html");
//returns TagName of the element
String value = driver.findElement(By.name("email_input")).getTagName();
# Navigate to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
# Returns TagName of the element
attr = driver.find_element(By.NAME, "email_input").tag_name
// Navigate to Url
driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/inputs.html");
// Returns TagName of the element
string attr = driver.FindElement(By.Name("email_input")).TagName;
# Navigate to url
driver.get 'https://www.selenium.dev/selenium/web/inputs.html'
# Returns TagName of the element
attr = driver.find_element(name: "email_input").tag_name
// Navigate to URL
await driver.get('https://www.selenium.dev/selenium/web/inputs.html');
// Returns TagName of the element
let value = await driver.findElement(By.name('email_input')).getTagName();
//navigates to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
//returns TagName of the element
val attr = driver.findElement(By.name("email_input")).getTagName()
用于获取参照元素的尺寸和坐标。
提取的数据主体包含以下详细信息:
// Navigate to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html");
// Returns height, width, x and y coordinates referenced element
Rectangle res = driver.findElement(By.name("range_input")).getRect();
// Rectangle class provides getX,getY, getWidth, getHeight methods
System.out.println(res.getX());
# Navigate to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
# Returns height, width, x and y coordinates referenced element
res = driver.find_element(By.NAME, "range_input").rect
// Navigate to Url
driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/inputs.html");
var res = driver.FindElement(By.Name("range_input"));
// Return x and y coordinates referenced element
System.Console.WriteLine(res.Location);
// Returns height, width
System.Console.WriteLine(res.Size);
# Navigate to url
driver.get 'https://www.selenium.dev/selenium/web/inputs.html'
# Returns height, width, x and y coordinates referenced element
res = driver.find_element(name: "range_input").rect
// Navigate to url
await driver.get('https://www.selenium.dev/selenium/web/inputs.html');
// Returns height, width, x and y coordinates referenced element
let element = await driver.findElement(By.name("range_input")).getRect();
// Navigate to url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
// Returns height, width, x and y coordinates referenced element
val res = driver.findElement(By.name("range_input")).rect
// Rectangle class provides getX,getY, getWidth, getHeight methods
println(res.getX())
获取当前浏览上下文中元素的特定计算样式属性的值。
// Navigate to Url
driver.get("https://www.selenium.dev/selenium/web/colorPage.html");
// Retrieves the computed style property 'color' of linktext
String cssValue = driver.findElement(By.id("namedColor")).getCssValue("background-color");
# Navigate to Url
driver.get('https://www.selenium.dev/selenium/web/colorPage.html')
# Retrieves the computed style property 'color' of linktext
cssValue = driver.find_element(By.ID, "namedColor").value_of_css_property('background-color')
// Navigate to Url
driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/colorPage.html");
// Retrieves the computed style property 'color' of linktext
String cssValue = driver.FindElement(By.Id("namedColor")).GetCssValue("background-color");
# Navigate to Url
driver.get 'https://www.selenium.dev/selenium/web/colorPage.html'
# Retrieves the computed style property 'color' of linktext
cssValue = driver.find_element(:id, 'namedColor').css_value('background-color')
// Navigate to Url
await driver.get('https://www.selenium.dev/selenium/web/colorPage.html');
// Retrieves the computed style property 'color' of linktext
let cssValue = await driver.findElement(By.id("namedColor")).getCssValue('background-color');
// Navigate to Url
driver.get("https://www.selenium.dev/selenium/web/colorPage.html")
// Retrieves the computed style property 'color' of linktext
val cssValue = driver.findElement(By.id("namedColor")).getCssValue("background-color")
获取特定元素渲染后的文本内容。
// Navigate to url
driver.get("https://www.selenium.dev/selenium/web/linked_image.html");
// Retrieves the text of the element
String text = driver.findElement(By.id("justanotherlink")).getText();
# Navigate to url
driver.get("https://www.selenium.dev/selenium/web/linked_image.html")
# Retrieves the text of the element
text = driver.find_element(By.ID, "justanotherlink").text
// Navigate to url
driver.Url="https://www.selenium.dev/selenium/web/linked_image.html";
// Retrieves the text of the element
String text = driver.FindElement(By.Id("justanotherlink")).Text;
# Navigate to url
driver.get 'https://www.selenium.dev/selenium/web/linked_image.html'
# Retrieves the text of the element
text = driver.find_element(:id, 'justanotherlink').text
// Navigate to URL
await driver.get('https://www.selenium.dev/selenium/web/linked_image.html');
// retrieves the text of the element
let text = await driver.findElement(By.id('justanotherlink')).getText();
// Navigate to URL
driver.get("https://www.selenium.dev/selenium/web/linked_image.html")
// retrieves the text of the element
val text = driver.findElement(By.id("justanotherlink")).getText()
获取与 DOM 属性关联的运行时的值。 它返回与该元素的 DOM 特性或属性关联的数据。
//Navigate to the url
driver.get("https://www.selenium.dev/selenium/web/inputs.html");
//identify the email text box
WebElement emailTxt = driver.findElement(By.name(("email_input")));
//fetch the value property associated with the textbox
String valueInfo = eleSelLink.getAttribute("value");
# Navigate to the url
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
# Identify the email text box
email_txt = driver.find_element(By.NAME, "email_input")
# Fetch the value property associated with the textbox
value_info = email_txt.get_attribute("value")
//Navigate to the url
driver.Url="https://www.selenium.dev/selenium/web/inputs.html";
//identify the email text box
IWebElement emailTxt = driver.FindElement(By.Name(("email_input")));
//fetch the value property associated with the textbox
String valueInfo = eleSelLink.GetAttribute("value");
# Navigate to the url
driver.get("https://www.selenium.dev/selenium/web/inputs.html");
#identify the email text box
email_element=driver.find_element(name: 'email_input')
#fetch the value property associated with the textbox
emailVal = email_element.attribute("value");
// Navigate to the Url
await driver.get("https://www.selenium.dev/selenium/web/inputs.html");
// identify the email text box
const emailElement = await driver.findElements(By.xpath('//input[@name="email_input"]'));
//fetch the attribute "name" associated with the textbox
const nameAttribute = await emailElement.getAttribute("name");
// Navigate to URL
driver.get("https://www.selenium.dev/selenium/web/inputs.html")
//fetch the value property associated with the textbox
val attr = driver.findElement(By.name("email_input")).getAttribute("value")
从浏览器中读取当前页面的标题:
driver.getTitle();
driver.title
driver.Title;
driver.title
await driver.getTitle();
driver.title
您可以从浏览器的地址栏读取当前的 URL,使用:
driver.getCurrentUrl();
driver.current_url
driver.Url;
driver.current_url
await driver.getCurrentUrl();
driver.currentUrl
启动浏览器后你要做的第一件事就是打开你的网站。这可以通过一行代码实现:
// 简便的方法
driver.get("https://selenium.dev");
// 更长的方法
driver.navigate().to("https://selenium.dev");
driver.get("https://selenium.dev")
driver.Navigate().GoToUrl(@"https://selenium.dev");
# 简便的方法
driver.get 'https://selenium.dev'
# 更长的方法
driver.navigate.to 'https://selenium.dev'
await driver.get('https://selenium.dev');
// 简便的方法
driver.get("https://selenium.dev")
// 更长的方法
driver.navigate().to("https://selenium.dev")
按下浏览器的后退按钮:
driver.navigate().back();
driver.back()
driver.Navigate().Back();
driver.navigate.back
await driver.navigate().back();
driver.navigate().back()
按下浏览器的前进键:
driver.navigate().forward();
driver.forward()
driver.Navigate().Forward();
driver.navigate.forward
await driver.navigate().forward();
driver.navigate().forward()
刷新当前页面:
driver.navigate().refresh();
driver.refresh()
driver.Navigate().Refresh();
driver.navigate.refresh
await driver.navigate().refresh();
driver.navigate().refresh()
WebDriver提供了一个API, 用于处理JavaScript提供的三种类型的原生弹窗消息. 这些弹窗由浏览器提供限定的样式.
其中最基本的称为警告框, 它显示一条自定义消息, 以及一个用于关闭该警告的按钮, 在大多数浏览器中标记为"确定"(OK). 在大多数浏览器中, 也可以通过按"关闭"(close)按钮将其关闭, 但这始终与“确定”按钮具有相同的作用. 查看样例警告框.
WebDriver可以从弹窗获取文本并接受或关闭这些警告.
//Click the link to activate the alert
driver.findElement(By.linkText("See an example alert")).click();
//Wait for the alert to be displayed and store it in a variable
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
//Store the alert text in a variable
String text = alert.getText();
//Press the OK button
alert.accept();
# Click the link to activate the alert
driver.find_element(By.LINK_TEXT, "See an example alert").click()
# Wait for the alert to be displayed and store it in a variable
alert = wait.until(expected_conditions.alert_is_present())
# Store the alert text in a variable
text = alert.text
# Press the OK button
alert.accept()
//Click the link to activate the alert
driver.FindElement(By.LinkText("See an example alert")).Click();
//Wait for the alert to be displayed and store it in a variable
IAlert alert = wait.Until(ExpectedConditions.AlertIsPresent());
//Store the alert text in a variable
string text = alert.Text;
//Press the OK button
alert.Accept();
# Click the link to activate the alert
driver.find_element(:link_text, 'See an example alert').click
# Store the alert reference in a variable
alert = driver.switch_to.alert
# Store the alert text in a variable
alert_text = alert.text
# Press on OK button
alert.accept
//Click the link to activate the alert
await driver.findElement(By.linkText('See an example alert')).click();
// Wait for the alert to be displayed
await driver.wait(until.alertIsPresent());
// Store the alert in a variable
let alert = await driver.switchTo().alert();
//Store the alert text in a variable
let alertText = await alert.getText();
//Press the OK button
await alert.accept();
// Note: To use await, the above code should be inside an async function
//Click the link to activate the alert
driver.findElement(By.linkText("See an example alert")).click()
//Wait for the alert to be displayed and store it in a variable
val alert = wait.until(ExpectedConditions.alertIsPresent())
//Store the alert text in a variable
val text = alert.getText()
//Press the OK button
alert.accept()
确认框类似于警告框, 不同之处在于用户还可以选择取消消息. 查看样例确认框.
此示例还呈现了警告的另一种实现:
//Click the link to activate the alert
driver.findElement(By.linkText("See a sample confirm")).click();
//Wait for the alert to be displayed
wait.until(ExpectedConditions.alertIsPresent());
//Store the alert in a variable
Alert alert = driver.switchTo().alert();
//Store the alert in a variable for reuse
String text = alert.getText();
//Press the Cancel button
alert.dismiss();
# Click the link to activate the alert
driver.find_element(By.LINK_TEXT, "See a sample confirm").click()
# Wait for the alert to be displayed
wait.until(expected_conditions.alert_is_present())
# Store the alert in a variable for reuse
alert = driver.switch_to.alert
# Store the alert text in a variable
text = alert.text
# Press the Cancel button
alert.dismiss()
//Click the link to activate the alert
driver.FindElement(By.LinkText("See a sample confirm")).Click();
//Wait for the alert to be displayed
wait.Until(ExpectedConditions.AlertIsPresent());
//Store the alert in a variable
IAlert alert = driver.SwitchTo().Alert();
//Store the alert in a variable for reuse
string text = alert.Text;
//Press the Cancel button
alert.Dismiss();
# Click the link to activate the alert
driver.find_element(:link_text, 'See a sample confirm').click
# Store the alert reference in a variable
alert = driver.switch_to.alert
# Store the alert text in a variable
alert_text = alert.text
# Press on Cancel button
alert.dismiss
//Click the link to activate the alert
await driver.findElement(By.linkText('See a sample confirm')).click();
// Wait for the alert to be displayed
await driver.wait(until.alertIsPresent());
// Store the alert in a variable
let alert = await driver.switchTo().alert();
//Store the alert text in a variable
let alertText = await alert.getText();
//Press the Cancel button
await alert.dismiss();
// Note: To use await, the above code should be inside an async function
//Click the link to activate the alert
driver.findElement(By.linkText("See a sample confirm")).click()
//Wait for the alert to be displayed
wait.until(ExpectedConditions.alertIsPresent())
//Store the alert in a variable
val alert = driver.switchTo().alert()
//Store the alert in a variable for reuse
val text = alert.text
//Press the Cancel button
alert.dismiss()
提示框与确认框相似, 不同之处在于它们还包括文本输入. 与处理表单元素类似, 您可以使用WebDriver的sendKeys来填写响应. 这将完全替换占位符文本. 按下取消按钮将不会提交任何文本. 查看样例提示框.
//Click the link to activate the alert
driver.findElement(By.linkText("See a sample prompt")).click();
//Wait for the alert to be displayed and store it in a variable
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
//Type your message
alert.sendKeys("Selenium");
//Press the OK button
alert.accept();
# Click the link to activate the alert
driver.find_element(By.LINK_TEXT, "See a sample prompt").click()
# Wait for the alert to be displayed
wait.until(expected_conditions.alert_is_present())
# Store the alert in a variable for reuse
alert = Alert(driver)
# Type your message
alert.send_keys("Selenium")
# Press the OK button
alert.accept()
//Click the link to activate the alert
driver.FindElement(By.LinkText("See a sample prompt")).Click();
//Wait for the alert to be displayed and store it in a variable
IAlert alert = wait.Until(ExpectedConditions.AlertIsPresent());
//Type your message
alert.SendKeys("Selenium");
//Press the OK button
alert.Accept();
# Click the link to activate the alert
driver.find_element(:link_text, 'See a sample prompt').click
# Store the alert reference in a variable
alert = driver.switch_to.alert
# Type a message
alert.send_keys("selenium")
# Press on Ok button
alert.accept
//Click the link to activate the alert
await driver.findElement(By.linkText('See a sample prompt')).click();
// Wait for the alert to be displayed
await driver.wait(until.alertIsPresent());
// Store the alert in a variable
let alert = await driver.switchTo().alert();
//Type your message
await alert.sendKeys("Selenium");
//Press the OK button
await alert.accept();
//Note: To use await, the above code should be inside an async function
//Click the link to activate the alert
driver.findElement(By.linkText("See a sample prompt")).click()
//Wait for the alert to be displayed and store it in a variable
val alert = wait.until(ExpectedConditions.alertIsPresent())
//Type your message
alert.sendKeys("Selenium")
//Press the OK button
alert.accept()
Cookie是从网站发送并存储在您的计算机中的一小段数据. Cookies主要用于识别用户并加载存储的信息.
WebDriver API提供了一种使用内置的方法与Cookie进行交互:
这个方法常常用于将cookie添加到当前访问的上下文中. 添加Cookie仅接受一组已定义的可序列化JSON对象. 这里 是一个链接, 用于描述可接受的JSON键值的列表
首先, 您需要位于有效Cookie的域上. 如果您在开始与网站进行交互之前尝试预设cookie, 并且您的首页很大或需要一段时间才能加载完毕, 则可以选择在网站上找到一个较小的页面 (通常404页很小, 例如 http://example.com/some404page)
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
public class addCookie {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("http://www.example.com");
// Adds the cookie into current browser context
driver.manage().addCookie(new Cookie("key", "value"));
} finally {
driver.quit();
}
}
}
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("http://www.example.com")
# Adds the cookie into current browser context
driver.add_cookie({"name": "key", "value": "value"})
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace AddCookie {
class AddCookie {
public static void Main(string[] args) {
IWebDriver driver = new ChromeDriver();
try {
// Navigate to Url
driver.Navigate().GoToUrl("https://example.com");
// Adds the cookie into current browser context
driver.Manage().Cookies.AddCookie(new Cookie("key", "value"));
} finally {
driver.Quit();
}
}
}
}
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.get 'https://www.example.com'
# Adds the cookie into current browser context
driver.manage.add_cookie(name: "key", value: "value")
ensure
driver.quit
end
it('Create a cookie', async function() {
await driver.get('https://www.selenium.dev/selenium/web/blank.html');
// set a cookie on the current domain
await driver.manage().addCookie({ name: 'key', value: 'value' });
import org.openqa.selenium.Cookie
import org.openqa.selenium.chrome.ChromeDriver
fun main() {
val driver = ChromeDriver()
try {
driver.get("https://example.com")
// Adds the cookie into current browser context
driver.manage().addCookie(Cookie("key", "value"))
} finally {
driver.quit()
}
}
此方法返回与cookie名称匹配的序列化cookie数据中所有关联的cookie.
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
public class getCookieNamed {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("http://www.example.com");
driver.manage().addCookie(new Cookie("foo", "bar"));
// Get cookie details with named cookie 'foo'
Cookie cookie1 = driver.manage().getCookieNamed("foo");
System.out.println(cookie1);
} finally {
driver.quit();
}
}
}
from selenium import webdriver
driver = webdriver.Chrome()
# Navigate to url
driver.get("http://www.example.com")
# Adds the cookie into current browser context
driver.add_cookie({"name": "foo", "value": "bar"})
# Get cookie details with named cookie 'foo'
print(driver.get_cookie("foo"))
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace GetCookieNamed {
class GetCookieNamed {
public static void Main(string[] args) {
IWebDriver driver = new ChromeDriver();
try {
// Navigate to Url
driver.Navigate().GoToUrl("https://example.com");
driver.Manage().Cookies.AddCookie(new Cookie("foo", "bar"));
// Get cookie details with named cookie 'foo'
var cookie = driver.Manage().Cookies.GetCookieNamed("foo");
System.Console.WriteLine(cookie);
} finally {
driver.Quit();
}
}
}
}
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.get 'https://www.example.com'
driver.manage.add_cookie(name: "foo", value: "bar")
# Get cookie details with named cookie 'foo'
puts driver.manage.cookie_named('foo')
ensure
driver.quit
end
it('Read cookie', async function() {
await driver.get('https://www.selenium.dev/selenium/web/blank.html');
// set a cookie on the current domain
await driver.manage().addCookie({ name: 'foo', value: 'bar' });
// Get cookie details with named cookie 'foo'
await driver.manage().getCookie('foo').then(function(cookie) {
console.log('cookie details => ', cookie);
});
import org.openqa.selenium.Cookie
import org.openqa.selenium.chrome.ChromeDriver
fun main() {
val driver = ChromeDriver()
try {
driver.get("https://example.com")
driver.manage().addCookie(Cookie("foo", "bar"))
// Get cookie details with named cookie 'foo'
val cookie = driver.manage().getCookieNamed("foo")
println(cookie)
} finally {
driver.quit()
}
}
此方法会针对当前访问上下文返回“成功的序列化cookie数据”. 如果浏览器不再可用, 则返回错误.
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.Set;
public class getAllCookies {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("http://www.example.com");
// Add few cookies
driver.manage().addCookie(new Cookie("test1", "cookie1"));
driver.manage().addCookie(new Cookie("test2", "cookie2"));
// Get All available cookies
Set<Cookie> cookies = driver.manage().getCookies();
System.out.println(cookies);
} finally {
driver.quit();
}
}
}
from selenium import webdriver
driver = webdriver.Chrome()
# Navigate to url
driver.get("http://www.example.com")
driver.add_cookie({"name": "test1", "value": "cookie1"})
driver.add_cookie({"name": "test2", "value": "cookie2"})
# Get all available cookies
print(driver.get_cookies())
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace GetAllCookies {
class GetAllCookies {
public static void Main(string[] args) {
IWebDriver driver = new ChromeDriver();
try {
// Navigate to Url
driver.Navigate().GoToUrl("https://example.com");
driver.Manage().Cookies.AddCookie(new Cookie("test1", "cookie1"));
driver.Manage().Cookies.AddCookie(new Cookie("test2", "cookie2"));
// Get All available cookies
var cookies = driver.Manage().Cookies.AllCookies;
} finally {
driver.Quit();
}
}
}
}
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.get 'https://www.example.com'
driver.manage.add_cookie(name: "test1", value: "cookie1")
driver.manage.add_cookie(name: "test2", value: "cookie2")
# Get all available cookies
puts driver.manage.all_cookies
ensure
driver.quit
end
it('Read all cookies', async function() {
await driver.get('https://www.selenium.dev/selenium/web/blank.html');
// Add few cookies
await driver.manage().addCookie({ name: 'test1', value: 'cookie1' });
await driver.manage().addCookie({ name: 'test2', value: 'cookie2' });
// Get all Available cookies
await driver.manage().getCookies().then(function(cookies) {
console.log('cookie details => ', cookies);
});
import org.openqa.selenium.Cookie
import org.openqa.selenium.chrome.ChromeDriver
fun main() {
val driver = ChromeDriver()
try {
driver.get("https://example.com")
driver.manage().addCookie(Cookie("test1", "cookie1"))
driver.manage().addCookie(Cookie("test2", "cookie2"))
// Get All available cookies
val cookies = driver.manage().cookies
println(cookies)
} finally {
driver.quit()
}
}
此方法删除与提供的cookie名称匹配的cookie数据.
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
public class deleteCookie {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("http://www.example.com");
driver.manage().addCookie(new Cookie("test1", "cookie1"));
Cookie cookie1 = new Cookie("test2", "cookie2");
driver.manage().addCookie(cookie1);
// delete a cookie with name 'test1'
driver.manage().deleteCookieNamed("test1");
/*
Selenium Java bindings also provides a way to delete
cookie by passing cookie object of current browsing context
*/
driver.manage().deleteCookie(cookie1);
} finally {
driver.quit();
}
}
}
from selenium import webdriver
driver = webdriver.Chrome()
# Navigate to url
driver.get("http://www.example.com")
driver.add_cookie({"name": "test1", "value": "cookie1"})
driver.add_cookie({"name": "test2", "value": "cookie2"})
# Delete a cookie with name 'test1'
driver.delete_cookie("test1")
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace DeleteCookie {
class DeleteCookie {
public static void Main(string[] args) {
IWebDriver driver = new ChromeDriver();
try {
// Navigate to Url
driver.Navigate().GoToUrl("https://example.com");
driver.Manage().Cookies.AddCookie(new Cookie("test1", "cookie1"));
var cookie = new Cookie("test2", "cookie2");
driver.Manage().Cookies.AddCookie(cookie);
// delete a cookie with name 'test1'
driver.Manage().Cookies.DeleteCookieNamed("test1");
// Selenium .net bindings also provides a way to delete
// cookie by passing cookie object of current browsing context
driver.Manage().Cookies.DeleteCookie(cookie);
} finally {
driver.Quit();
}
}
}
}
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.get 'https://www.example.com'
driver.manage.add_cookie(name: "test1", value: "cookie1")
driver.manage.add_cookie(name: "test2", value: "cookie2")
# delete a cookie with name 'test1'
driver.manage.delete_cookie('test1')
ensure
driver.quit
end
it('Delete a cookie', async function() {
await driver.get('https://www.selenium.dev/selenium/web/blank.html');
// Add few cookies
await driver.manage().addCookie({ name: 'test1', value: 'cookie1' });
await driver.manage().addCookie({ name: 'test2', value: 'cookie2' });
// Delete a cookie with name 'test1'
await driver.manage().deleteCookie('test1');
// Get all Available cookies
await driver.manage().getCookies().then(function(cookies) {
console.log('cookie details => ', cookies);
});
import org.openqa.selenium.Cookie
import org.openqa.selenium.chrome.ChromeDriver
fun main() {
val driver = ChromeDriver()
try {
driver.get("https://example.com")
driver.manage().addCookie(Cookie("test1", "cookie1"))
val cookie1 = Cookie("test2", "cookie2")
driver.manage().addCookie(cookie1)
// delete a cookie with name 'test1'
driver.manage().deleteCookieNamed("test1")
// delete cookie by passing cookie object of current browsing context.
driver.manage().deleteCookie(cookie1)
} finally {
driver.quit()
}
}
此方法删除当前访问上下文的所有cookie.
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
public class deleteAllCookies {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("http://www.example.com");
driver.manage().addCookie(new Cookie("test1", "cookie1"));
driver.manage().addCookie(new Cookie("test2", "cookie2"));
// deletes all cookies
driver.manage().deleteAllCookies();
} finally {
driver.quit();
}
}
}
from selenium import webdriver
driver = webdriver.Chrome()
# Navigate to url
driver.get("http://www.example.com")
driver.add_cookie({"name": "test1", "value": "cookie1"})
driver.add_cookie({"name": "test2", "value": "cookie2"})
# Deletes all cookies
driver.delete_all_cookies()
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace DeleteAllCookies {
class DeleteAllCookies {
public static void Main(string[] args) {
IWebDriver driver = new ChromeDriver();
try {
// Navigate to Url
driver.Navigate().GoToUrl("https://example.com");
driver.Manage().Cookies.AddCookie(new Cookie("test1", "cookie1"));
driver.Manage().Cookies.AddCookie(new Cookie("test2", "cookie2"));
// deletes all cookies
driver.Manage().Cookies.DeleteAllCookies();
} finally {
driver.Quit();
}
}
}
}
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.get 'https://www.example.com'
driver.manage.add_cookie(name: "test1", value: "cookie1")
driver.manage.add_cookie(name: "test2", value: "cookie2")
# deletes all cookies
driver.manage.delete_all_cookies
ensure
driver.quit
end
it('Delete all cookies', async function() {
await driver.get('https://www.selenium.dev/selenium/web/blank.html');
// Add few cookies
await driver.manage().addCookie({ name: 'test1', value: 'cookie1' });
await driver.manage().addCookie({ name: 'test2', value: 'cookie2' });
// Delete all cookies
await driver.manage().deleteAllCookies();
import org.openqa.selenium.Cookie
import org.openqa.selenium.chrome.ChromeDriver
fun main() {
val driver = ChromeDriver()
try {
driver.get("https://example.com")
driver.manage().addCookie(Cookie("test1", "cookie1"))
driver.manage().addCookie(Cookie("test2", "cookie2"))
// deletes all cookies
driver.manage().deleteAllCookies()
} finally {
driver.quit()
}
}
此属性允许用户引导浏览器控制cookie, 是否与第三方站点发起的请求一起发送. 引入其是为了防止CSRF(跨站请求伪造)攻击.
Same-Site cookie属性接受以下两种参数作为指令
当sameSite属性设置为 Strict, cookie不会与来自第三方网站的请求一起发送.
当您将cookie sameSite属性设置为 Lax, cookie将与第三方网站发起的GET请求一起发送.
注意: 到目前为止, 此功能已在Chrome(80+版本), Firefox(79+版本)中提供, 并适用于Selenium 4以及更高版本.
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
public class cookieTest {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("http://www.example.com");
Cookie cookie = new Cookie.Builder("key", "value").sameSite("Strict").build();
Cookie cookie1 = new Cookie.Builder("key", "value").sameSite("Lax").build();
driver.manage().addCookie(cookie);
driver.manage().addCookie(cookie1);
System.out.println(cookie.getSameSite());
System.out.println(cookie1.getSameSite());
} finally {
driver.quit();
}
}
}
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("http://www.example.com")
# Adds the cookie into current browser context with sameSite 'Strict' (or) 'Lax'
driver.add_cookie({"name": "foo", "value": "value", 'sameSite': 'Strict'})
driver.add_cookie({"name": "foo1", "value": "value", 'sameSite': 'Lax'})
cookie1 = driver.get_cookie('foo')
cookie2 = driver.get_cookie('foo1')
print(cookie1)
print(cookie2)
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace SameSiteCookie {
class SameSiteCookie {
static void Main(string[] args) {
IWebDriver driver = new ChromeDriver();
try {
driver.Navigate().GoToUrl("http://www.example.com");
var cookie1Dictionary = new System.Collections.Generic.Dictionary<string, object>() {
{ "name", "test1" }, { "value", "cookie1" }, { "sameSite", "Strict" } };
var cookie1 = Cookie.FromDictionary(cookie1Dictionary);
var cookie2Dictionary = new System.Collections.Generic.Dictionary<string, object>() {
{ "name", "test2" }, { "value", "cookie2" }, { "sameSite", "Lax" } };
var cookie2 = Cookie.FromDictionary(cookie2Dictionary);
driver.Manage().Cookies.AddCookie(cookie1);
driver.Manage().Cookies.AddCookie(cookie2);
System.Console.WriteLine(cookie1.SameSite);
System.Console.WriteLine(cookie2.SameSite);
} finally {
driver.Quit();
}
}
}
}
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.get 'https://www.example.com'
# Adds the cookie into current browser context with sameSite 'Strict' (or) 'Lax'
driver.manage.add_cookie(name: "foo", value: "bar", same_site: "Strict")
driver.manage.add_cookie(name: "foo1", value: "bar", same_site: "Lax")
puts driver.manage.cookie_named('foo')
puts driver.manage.cookie_named('foo1')
ensure
driver.quit
end
it('Create cookies with sameSite', async function() {
await driver.get('https://www.selenium.dev/selenium/web/blank.html');
// set a cookie on the current domain with sameSite 'Strict' (or) 'Lax'
await driver.manage().addCookie({ name: 'key', value: 'value', sameSite: 'Strict' });
await driver.manage().addCookie({ name: 'key', value: 'value', sameSite: 'Lax' });
import org.openqa.selenium.Cookie
import org.openqa.selenium.chrome.ChromeDriver
fun main() {
val driver = ChromeDriver()
try {
driver.get("http://www.example.com")
val cookie = Cookie.Builder("key", "value").sameSite("Strict").build()
val cookie1 = Cookie.Builder("key", "value").sameSite("Lax").build()
driver.manage().addCookie(cookie)
driver.manage().addCookie(cookie1)
println(cookie.getSameSite())
println(cookie1.getSameSite())
} finally {
driver.quit()
}
}
框架是一种现在已被弃用的方法,用于从同一域中的多个文档构建站点布局。除非你使用的是 HTML5 之前的 webapp,否则你不太可能与他们合作。内嵌框架允许插入来自完全不同领域的文档,并且仍然经常使用。
如果您需要使用框架或 iframe, WebDriver 允许您以相同的方式使用它们。考虑 iframe 中的一个按钮。 如果我们使用浏览器开发工具检查元素,我们可能会看到以下内容:
<div id="modal">
<iframe id="buttonframe"name="myframe"src="https://seleniumhq.github.io">
<button>Click here</button>
</iframe>
</div>
如果不是 iframe,我们可能会使用如下方式点击按钮:
// 这不会工作
driver.findElement(By.tagName("button")).click();
# 这不会工作
driver.find_element(By.TAG_NAME, 'button').click()
// 这不会工作
driver.FindElement(By.TagName("button")).Click();
# 这不会工作
driver.find_element(:tag_name,'button').click
// 这不会工作
await driver.findElement(By.css('button')).click();
// 这不会工作
driver.findElement(By.tagName("button")).click()
但是,如果 iframe 之外没有按钮,那么您可能会得到一个 no such element 无此元素 的错误。 这是因为 Selenium 只知道顶层文档中的元素。为了与按钮进行交互,我们需要首先切换到框架, 这与切换窗口的方式类似。WebDriver 提供了三种切换到帧的方法。
使用 WebElement 进行切换是最灵活的选择。您可以使用首选的选择器找到框架并切换到它。
// 存储网页元素
WebElement iframe = driver.findElement(By.cssSelector("#modal>iframe"));
// 切换到 frame
driver.switchTo().frame(iframe);
// 现在可以点击按钮
driver.findElement(By.tagName("button")).click();
# 存储网页元素
iframe = driver.find_element(By.CSS_SELECTOR, "#modal > iframe")
# 切换到选择的 iframe
driver.switch_to.frame(iframe)
# 单击按钮
driver.find_element(By.TAG_NAME, 'button').click()
// 存储网页元素
IWebElement iframe = driver.FindElement(By.CssSelector("#modal>iframe"));
// 切换到 frame
driver.SwitchTo().Frame(iframe);
// 现在可以点击按钮
driver.FindElement(By.TagName("button")).Click();
# Store iframe web element
iframe = driver.find_element(:css,'#modal> iframe')
# 切换到 frame
driver.switch_to.frame iframe
# 单击按钮
driver.find_element(:tag_name,'button').click
// 存储网页元素
const iframe = driver.findElement(By.css('#modal> iframe'));
// 切换到 frame
await driver.switchTo().frame(iframe);
// 现在可以点击按钮
await driver.findElement(By.css('button')).click();
// 存储网页元素
val iframe = driver.findElement(By.cssSelector("#modal>iframe"))
// 切换到 frame
driver.switchTo().frame(iframe)
// 现在可以点击按钮
driver.findElement(By.tagName("button")).click()
如果您的 frame 或 iframe 具有 id 或 name 属性,则可以使用该属性。如果名称或 id 在页面上不是唯一的, 那么将切换到找到的第一个。
// 使用 ID
driver.switchTo().frame("buttonframe");
// 或者使用 name 代替
driver.switchTo().frame("myframe");
// 现在可以点击按钮
driver.findElement(By.tagName("button")).click();
# 通过 id 切换框架
driver.switch_to.frame('buttonframe')
# 单击按钮
driver.find_element(By.TAG_NAME, 'button').click()
// 使用 ID
driver.SwitchTo().Frame("buttonframe");
// 或者使用 name 代替
driver.SwitchTo().Frame("myframe");
// 现在可以点击按钮
driver.FindElement(By.TagName("button")).Click();
# Switch by ID
driver.switch_to.frame 'buttonframe'
# 单击按钮
driver.find_element(:tag_name,'button').click
// 使用 ID
await driver.switchTo().frame('buttonframe');
// 或者使用 name 代替
await driver.switchTo().frame('myframe');
// 现在可以点击按钮
await driver.findElement(By.css('button')).click();
// 使用 ID
driver.switchTo().frame("buttonframe")
// 或者使用 name 代替
driver.switchTo().frame("myframe")
// 现在可以点击按钮
driver.findElement(By.tagName("button")).click()
还可以使用frame的索引, 例如可以使用JavaScript中的 window.frames 进行查询.
// 切换到第 2 个框架
driver.switchTo().frame(1);
# 切换到第 2 个框架
driver.switch_to.frame(1)
// 切换到第 2 个框架
driver.SwitchTo().Frame(1);
# 基于索引切换到第 2 个 iframe
iframe = driver.find_elements(By.TAG_NAME,'iframe')[1]
# 切换到选择的 iframe
driver.switch_to.frame(iframe)
// 切换到第 2 个框架
await driver.switchTo().frame(1);
// 切换到第 2 个框架
driver.switchTo().frame(1)
离开 iframe 或 frameset,切换回默认内容,如下所示:
// 回到顶层
driver.switchTo().defaultContent();
# 切回到默认内容
driver.switch_to.default_content()
// 回到顶层
driver.SwitchTo().DefaultContent();
# 回到顶层
driver.switch_to.default_content
// 回到顶层
await driver.switchTo().defaultContent();
// 回到顶层
driver.switchTo().defaultContent()
WebDriver 没有区分窗口和标签页。如果你的站点打开了一个新标签页或窗口,Selenium 将允许您使用窗口句柄来处理它。 每个窗口都有一个唯一的标识符,该标识符在单个会话中保持持久性。你可以使用以下方法获得当前窗口的窗口句柄:
driver.getWindowHandle();
driver.current_window_handle
driver.CurrentWindowHandle;
driver.window_handle
await driver.getWindowHandle();
driver.windowHandle
单击在 <a href=“https://seleniumhq.github.io"target="_blank”>新窗口 中打开链接, 则屏幕会聚焦在新窗口或新标签页上,但 WebDriver 不知道操作系统认为哪个窗口是活动的。 要使用新窗口,您需要切换到它。 如果只有两个选项卡或窗口被打开,并且你知道从哪个窗口开始, 则你可以遍历 WebDriver, 通过排除法可以看到两个窗口或选项卡,然后切换到你需要的窗口或选项卡。
不过,Selenium 4 提供了一个新的 api NewWindow 它创建一个新选项卡 (或) 新窗口并自动切换到它。
// 存储原始窗口的 ID
String originalWindow = driver.getWindowHandle();
// 检查一下,我们还没有打开其他的窗口
assert driver.getWindowHandles().size() == 1;
// 点击在新窗口中打开的链接
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;
}
}
// 等待新标签完成加载内容
wait.until(titleIs("Selenium documentation"));
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 启动驱动程序
with webdriver.Firefox() as driver:
# 打开网址
driver.get("https://seleniumhq.github.io")
# 设置等待
wait = WebDriverWait(driver, 10)
# 存储原始窗口的 ID
original_window = driver.current_window_handle
# 检查一下,我们还没有打开其他的窗口
assert len(driver.window_handles) == 1
# 单击在新窗口中打开的链接
driver.find_element(By.LINK_TEXT, "new window").click()
# 等待新窗口或标签页
wait.until(EC.number_of_windows_to_be(2))
# 循环执行,直到找到一个新的窗口句柄
for window_handle in driver.window_handles:
if window_handle != original_window:
driver.switch_to.window(window_handle)
break
# 等待新标签页完成加载内容
wait.until(EC.title_is("SeleniumHQ Browser Automation"))
// 存储原始窗口的 ID
string originalWindow = driver.CurrentWindowHandle;
// 检查一下,我们还没有打开其他的窗口
Assert.AreEqual(driver.WindowHandles.Count, 1);
// 单击在新窗口中打开的链接
driver.FindElement(By.LinkText("new window")).Click();
// 等待新窗口或标签页
wait.Until(wd => wd.WindowHandles.Count == 2);
// 循环执行,直到找到一个新的窗口句柄
foreach(string window in driver.WindowHandles)
{if(originalWindow != window)
{driver.SwitchTo().Window(window);
break;
}
}
// 等待新标签页完成加载内容
wait.Until(wd => wd.Title == "Selenium documentation");
# 存储原始窗口的 ID
original_window = driver.window_handle
#检查一下,我们还没有打开其他的窗口
assert(driver.window_handles.length == 1,'Expected one window')
#点击在新窗口中打开的链接
driver.find_element(link:'new window').click
#等待新窗口或标签页
wait.until {driver.window_handles.length == 2}
#循环执行,直到找到一个新的窗口句柄
driver.window_handles.each do |handle|
if handle != original_window
driver.switch_to.window handle
break
end
end
#等待新标签页完成加载内容
wait.until {driver.title =='Selenium documentation'}
// 存储原始窗口的 ID
const originalWindow = await driver.getWindowHandle();
// 检查一下,我们还没有打开其他的窗口
assert((await driver.getAllWindowHandles()).length === 1);
// 点击在新窗口中打开的链接
await driver.findElement(By.linkText('new window')).click();
// 等待新窗口或标签页
await driver.wait(async () => (await driver.getAllWindowHandles()).length === 2,
10000
);
// 循环执行,直到找到一个新的窗口句柄
const windows = await driver.getAllWindowHandles();
windows.forEach(async handle => {if (handle !== originalWindow) {await driver.switchTo().window(handle);
}
});
// 等待新标签页完成加载内容
await driver.wait(until.titleIs('Selenium documentation'), 10000);
// 存储原始窗口的 ID
val originalWindow = driver.getWindowHandle()
// 检查一下,我们还没有打开其他的窗口
assert(driver.getWindowHandles().size() === 1)
// 点击在新窗口中打开的链接
driver.findElement(By.linkText("new window")).click()
// 等待新窗口或标签页
wait.until(numberOfWindowsToBe(2))
// 循环执行,直到找到一个新的窗口句柄
for (windowHandle in driver.getWindowHandles()) {
if (!originalWindow.contentEquals(windowHandle)) {
driver.switchTo().window(windowHandle)
break
}
}
// 等待新标签页完成加载内容
wait.until(titleIs("Selenium documentation"))
创建一个新窗口 (或) 标签页,屏幕焦点将聚焦在新窗口或标签在上。您不需要切换到新窗口 (或) 标签页。如果除了新窗口之外, 您打开了两个以上的窗口 (或) 标签页,您可以通过遍历 WebDriver 看到两个窗口或选项卡,并切换到非原始窗口。
注意: 该特性适用于 Selenium 4 及其后续版本。
// 打开新标签页并切换到新标签页
driver.switchTo().newWindow(WindowType.TAB);
// 打开一个新窗口并切换到新窗口
driver.switchTo().newWindow(WindowType.WINDOW);
# 打开新标签页并切换到新标签页
driver.switch_to.new_window('tab')
# 打开一个新窗口并切换到新窗口
driver.switch_to.new_window('window')
// 打开新标签页并切换到新标签页
driver.SwitchTo().NewWindow(WindowType.Tab)
// 打开一个新窗口并切换到新窗口
driver.SwitchTo().NewWindow(WindowType.Window)
# 注意:ruby 中的 new_window 只打开一个新标签页(或)窗口,不会自动切换
# 用户必须切换到新选项卡 (或) 新窗口
# 打开新标签页并切换到新标签页
driver.manage.new_window(:tab)
# 打开一个新窗口并切换到新窗口
driver.manage.new_window(:window)
// 打开新标签页并切换到新标签页
await driver.switchTo().newWindow('tab');
// 打开一个新窗口并切换到新窗口
await driver.switchTo().newWindow('window');
// 打开新标签页并切换到新标签页
driver.switchTo().newWindow(WindowType.TAB)
// 打开一个新窗口并切换到新窗口
driver.switchTo().newWindow(WindowType.WINDOW)
当你完成了一个窗口或标签页的工作时,_并且_它不是浏览器中最后一个打开的窗口或标签页时,你应该关闭它并切换回你之前使用的窗口。 假设您遵循了前一节中的代码示例,您将把前一个窗口句柄存储在一个变量中。把这些放在一起,你会得到:
//关闭标签页或窗口
driver.close();
//切回到之前的标签页或窗口
driver.switchTo().window(originalWindow);
#关闭标签页或窗口
driver.close()
#切回到之前的标签页或窗口
driver.switch_to.window(original_window)
//关闭标签页或窗口
driver.Close();
//切回到之前的标签页或窗口
driver.SwitchTo().Window(originalWindow);
#关闭标签页或窗口
driver.close
#切回到之前的标签页或窗口
driver.switch_to.window original_window
//关闭标签页或窗口
await driver.close();
//切回到之前的标签页或窗口
await driver.switchTo().window(originalWindow);
//关闭标签页或窗口
driver.close()
//切回到之前的标签页或窗口
driver.switchTo().window(originalWindow)
如果在关闭一个窗口后忘记切换回另一个窗口句柄,WebDriver 将在当前关闭的页面上执行,并触发一个 No Such Window Exception 无此窗口异常。必须切换回有效的窗口句柄才能继续执行。
当你完成了浏览器会话,你应该调用 quit 退出,而不是 close 关闭:
driver.quit();
driver.quit()
driver.Quit();
driver.quit
await driver.quit();
driver.quit()
调用 quit() 失败将留下额外的后台进程和端口运行在机器上,这可能在以后导致一些问题。
有的测试框架提供了一些方法和注释,您可以在测试结束时放入 teardown() 方法中。
/**
* 使用 JUnit 的例子
* https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/AfterAll.html
*/
@AfterAll
public static void tearDown() {
driver.quit();
}
# unittest teardown
# https://docs.python.org/3/library/unittest.html?highlight=teardown#unittest.TestCase.tearDown
def tearDown(self):
self.driver.quit()
/*
使用 Visual Studio 的 UnitTesting 的例子
https://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.aspx
*/
[TestCleanup]
public void TearDown()
{driver.Quit();
}
# UnitTest Teardown
# https://www.rubydoc.info/github/test-unit/test-unit/Test/Unit/TestCase
def teardown
@driver.quit
end
/**
* 使用 Mocha 的例子
* https://mochajs.org/#hooks
*/
after('Tear down', async function () {await driver.quit();
});
/**
* 使用 JUnit 的例子
* https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/AfterAll.html
*/
@AfterAll
fun tearDown() {
driver.quit()
}
如果不在测试上下文中运行 WebDriver,您可以考虑使用 try / finally
,这是大多数语言都提供的,
这样一个异常处理仍然可以清理 WebDriver 会话。
try {
//WebDriver 代码…
} finally {
driver.quit();
}
try:
#WebDriver 代码…
finally:
driver.quit()
try {//WebDriver 代码…} finally {driver.Quit();
}
begin
#WebDriver 代码…
ensure
driver.quit
end
try {//WebDriver 代码…} finally {await driver.quit();
}
try {//WebDriver 代码…} finally {driver.quit()
}
Python 的 WebDriver 现在支持 Python 上下文管理器,当使用 with 关键字时,可以在执行结束时自动退出驱动程序。
with webdriver.Firefox() as driver:
# WebDriver 代码…
# 在此缩进位置后 WebDriver 会自动退出
屏幕分辨率会影响 web 应用程序的呈现方式,因此 WebDriver 提供了移动和调整浏览器窗口大小的机制。
获取浏览器窗口的大小(以像素为单位)。
// 分别获取每个尺寸
int width = driver.manage().window().getSize().getWidth();
int height = driver.manage().window().getSize().getHeight();
// 或者存储尺寸并在以后查询它们
Dimension size = driver.manage().window().getSize();
int width1 = size.getWidth();
int height1 = size.getHeight();
# 分别获取每个尺寸
width = driver.get_window_size().get("width")
height = driver.get_window_size().get("height")
# 或者存储尺寸并在以后查询它们
size = driver.get_window_size()
width1 = size.get("width")
height1 = size.get("height")
// 分别获取每个尺寸
int width = driver.Manage().Window.Size.Width;
int height = driver.Manage().Window.Size.Height;
// 或者存储尺寸并在以后查询它们
System.Drawing.Size size = driver.Manage().Window.Size;
int width1 = size.Width;
int height1 = size.Height;
# 分别获取每个尺寸
width = driver.manage.window.size.width
height = driver.manage.window.size.height
# 或者存储尺寸并在以后查询它们
size = driver.manage.window.size
width1 = size.width
height1 = size.height
// 分别获取每个尺寸
const {width, height} = await driver.manage().window().getRect();
// 或者存储尺寸并在以后查询它们
const rect = await driver.manage().window().getRect();
const width1 = rect.width;
const height1 = rect.height;
// 分别获取每个尺寸
val width = driver.manage().window().size.width
val height = driver.manage().window().size.height
// 或者存储尺寸并在以后查询它们
val size = driver.manage().window().size
val width1 = size.width
val height1 = size.height
恢复窗口并设置窗口大小。
driver.manage().window().setSize(new Dimension(1024, 768));
driver.set_window_size(1024, 768)
driver.Manage().Window.Size = new Size(1024, 768);
driver.manage.window.resize_to(1024,768)
await driver.manage().window().setRect({width: 1024, height: 768});
driver.manage().window().size = Dimension(1024, 768)
获取浏览器窗口左上角的坐标。
// 分别获取每个尺寸
int x = driver.manage().window().getPosition().getX();
int y = driver.manage().window().getPosition().getY();
// 或者存储尺寸并在以后查询它们
Point position = driver.manage().window().getPosition();
int x1 = position.getX();
int y1 = position.getY();
# 分别获取每个尺寸
x = driver.get_window_position().get('x')
y = driver.get_window_position().get('y')
# 或者存储尺寸并在以后查询它们
position = driver.get_window_position()
x1 = position.get('x')
y1 = position.get('y')
// 分别获取每个尺寸
int x = driver.Manage().Window.Position.X;
int y = driver.Manage().Window.Position.Y;
// 或者存储尺寸并在以后查询它们
Point position = driver.Manage().Window.Position;
int x1 = position.X;
int y1 = position.Y;
#Access each dimension individually
x = driver.manage.window.position.x
y = driver.manage.window.position.y
# Or store the dimensions and query them later
rect = driver.manage.window.rect
x1 = rect.x
y1 = rect.y
// 分别获取每个尺寸
const {x, y} = await driver.manage().window().getRect();
// 或者存储尺寸并在以后查询它们
const rect = await driver.manage().window().getRect();
const x1 = rect.x;
const y1 = rect.y;
// 分别获取每个尺寸
val x = driver.manage().window().position.x
val y = driver.manage().window().position.y
// 或者存储尺寸并在以后查询它们
val position = driver.manage().window().position
val x1 = position.x
val y1 = position.y
将窗口移动到设定的位置。
// 将窗口移动到主显示器的左上角
driver.manage().window().setPosition(new Point(0, 0));
# 将窗口移动到主显示器的左上角
driver.set_window_position(0, 0)
// 将窗口移动到主显示器的左上角
driver.Manage().Window.Position = new Point(0, 0);
driver.manage.window.move_to(0,0)
// 将窗口移动到主显示器的左上角
await driver.manage().window().setRect({x: 0, y: 0});
// 将窗口移动到主显示器的左上角
driver.manage().window().position = Point(0,0)
扩大窗口。对于大多数操作系统,窗口将填满屏幕,而不会阻挡操作系统自己的菜单和工具栏。
driver.manage().window().maximize();
driver.maximize_window()
driver.Manage().Window.Maximize();
driver.manage.window.maximize
await driver.manage().window().maximize();
driver.manage().window().maximize()
最小化当前浏览上下文的窗口. 这种命令的精准行为将作用于各个特定的窗口管理器.
最小化窗口通常将窗口隐藏在系统托盘中.
注意: 此功能适用于Selenium 4以及更高版本.
driver.manage().window().minimize();
driver.minimize_window()
driver.Manage().Window.Minimize();
driver.manage.window.minimize
await driver.manage().window().minimize();
driver.manage().window().minimize()
填充整个屏幕,类似于在大多数浏览器中按下 F11。
driver.manage().window().fullscreen();
driver.fullscreen_window()
driver.Manage().Window.FullScreen();
driver.manage.window.full_screen
await driver.manage().window().fullscreen();
driver.manage().window().fullscreen()
用于捕获当前浏览上下文的屏幕截图. WebDriver端点 屏幕截图 返回以Base64格式编码的屏幕截图.
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.chrome.ChromeDriver;
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();
}
}
from selenium import webdriver
driver = webdriver.Chrome()
# Navigate to url
driver.get("http://www.example.com")
# Returns and base64 encoded string into image
driver.save_screenshot('./image.png')
driver.quit()
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
var driver = new ChromeDriver();
driver.Navigate().GoToUrl("http://www.example.com");
Screenshot screenshot = (driver as ITakesScreenshot).GetScreenshot();
screenshot.SaveAsFile("screenshot.png", ScreenshotImageFormat.Png); // Format values are Bmp, Gif, Jpeg, Png, Tiff
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.get 'https://example.com/'
# Takes and Stores the screenshot in specified path
driver.save_screenshot('./image.png')
end
let {Builder} = require('selenium-webdriver');
let fs = require('fs');
(async function example() {
let driver = await new Builder()
.forBrowser('chrome')
.build();
await driver.get('https://www.example.com');
// Returns base64 encoded string
let encodedString = await driver.takeScreenshot();
await fs.writeFileSync('./image.png', encodedString, 'base64');
await driver.quit();
}())
import com.oracle.tools.packager.IOUtils.copyFile
import org.openqa.selenium.*
import org.openqa.selenium.chrome.ChromeDriver
import java.io.File
fun main(){
val driver = ChromeDriver()
driver.get("https://www.example.com")
val scrFile = (driver as TakesScreenshot).getScreenshotAs<File>(OutputType.FILE)
copyFile(scrFile, File("./image.png"))
driver.quit()
}
用于捕获当前浏览上下文的元素的屏幕截图. WebDriver端点 屏幕截图 返回以Base64格式编码的屏幕截图.
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import java.io.File;
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();
}
}
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
# Navigate to url
driver.get("http://www.example.com")
ele = driver.find_element(By.CSS_SELECTOR, 'h1')
# Returns and base64 encoded string into image
ele.screenshot('./image.png')
driver.quit()
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
// Webdriver
var driver = new ChromeDriver();
driver.Navigate().GoToUrl("http://www.example.com");
// Fetch element using FindElement
var webElement = driver.FindElement(By.CssSelector("h1"));
// Screenshot for the element
var elementScreenshot = (webElement as ITakesScreenshot).GetScreenshot();
elementScreenshot.SaveAsFile("screenshot_of_element.png");
# Works with Selenium4-alpha7 Ruby bindings and above
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.get 'https://example.com/'
ele = driver.find_element(:css, 'h1')
# Takes and Stores the element screenshot in specified path
ele.save_screenshot('./image.jpg')
end
const {Builder, By} = require('selenium-webdriver');
let fs = require('fs');
(async function example() {
let driver = await new Builder()
.forBrowser('chrome')
.build();
await driver.get('https://www.example.com');
let ele = await driver.findElement(By.css("h1"));
// Captures the element screenshot
let encodedString = await ele.takeScreenshot(true);
await fs.writeFileSync('./image.png', encodedString, 'base64');
await driver.quit();
}())
import org.apache.commons.io.FileUtils
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.*
import java.io.File
fun main() {
val driver = ChromeDriver()
driver.get("https://www.example.com")
val element = driver.findElement(By.cssSelector("h1"))
val scrFile: File = element.getScreenshotAs(OutputType.FILE)
FileUtils.copyFile(scrFile, File("./image.png"))
driver.quit()
}
在当前frame或者窗口的上下文中,执行JavaScript代码片段.
//Creating the JavascriptExecutor interface object by Type casting
JavascriptExecutor js = (JavascriptExecutor)driver;
//Button Element
WebElement button =driver.findElement(By.name("btnLogin"));
//Executing JavaScript to click on element
js.executeScript("arguments[0].click();", button);
//Get return value from script
String text = (String) js.executeScript("return arguments[0].innerText", button);
//Executing JavaScript directly
js.executeScript("console.log('hello world')");
# Stores the header element
header = driver.find_element(By.CSS_SELECTOR, "h1")
# Executing JavaScript to capture innerText of header element
driver.execute_script('return arguments[0].innerText', header)
//creating Chromedriver instance
IWebDriver driver = new ChromeDriver();
//Creating the JavascriptExecutor interface object by Type casting
IJavaScriptExecutor js = (IJavaScriptExecutor) driver;
//Button Element
IWebElement button = driver.FindElement(By.Name("btnLogin"));
//Executing JavaScript to click on element
js.ExecuteScript("arguments[0].click();", button);
//Get return value from script
String text = (String)js.ExecuteScript("return arguments[0].innerText", button);
//Executing JavaScript directly
js.ExecuteScript("console.log('hello world')");
# Stores the header element
header = driver.find_element(css: 'h1')
# Get return value from script
result = driver.execute_script("return arguments[0].innerText", header)
# Executing JavaScript directly
driver.execute_script("alert('hello world')")
// Stores the header element
let header = await driver.findElement(By.css('h1'));
// Executing JavaScript to capture innerText of header element
let text = await driver.executeScript('return arguments[0].innerText', header);
// Stores the header element
val header = driver.findElement(By.cssSelector("h1"))
// Get return value from script
val result = driver.executeScript("return arguments[0].innerText", header)
// Executing JavaScript directly
driver.executeScript("alert('hello world')")
打印当前浏览器内的页面
注意: 此功能需要无头模式下的Chromium浏览器
import org.openqa.selenium.print.PrintOptions;
driver.get("https://www.selenium.dev");
printer = (PrintsPage) driver;
PrintOptions printOptions = new PrintOptions();
printOptions.setPageRanges("1-2");
Pdf pdf = printer.print(printOptions);
String content = pdf.getContent();
from selenium.webdriver.common.print_page_options import PrintOptions
print_options = PrintOptions()
print_options.page_ranges = ['1-2']
driver.get("printPage.html")
base64code = driver.print_page(print_options)
// code sample not available please raise a PR
driver.navigate_to 'https://www.selenium.dev'
base64encodedContent = driver.print_page(orientation: 'landscape')
const {Builder} = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
let opts = new chrome.Options();
let fs = require('fs');
(async function example() {
let driver = new Builder()
.forBrowser('chrome')
.setChromeOptions(opts.headless())
.build();
await driver.get('https://www.selenium.dev');
try {
let base64 = await driver.printPage({pageRanges:["1-2"]});
await fs.writeFileSync('./test.pdf', base64, 'base64');
} catch (e) {
console.log(e)
}
await driver.quit();
driver.get("https://www.selenium.dev")
val printer = driver as PrintsPage
val printOptions = PrintOptions()
printOptions.setPageRanges("1-2")
val pdf: Pdf = printer.print(printOptions)
val content = pdf.content
Web 应用程序可以启用基于公钥的身份验证机制(称为 Web 身份验证)以无密码方式对用户进行身份验证。 Web 身份验证 定义了允许用户创建公钥凭据并将其注册到身份验证器的 API。 身份验证器可以是硬件设备或软件实体,用于存储用户的公钥凭证并根据请求检索它们。
顾名思义,虚拟身份验证器模拟此类身份验证器进行测试。
虚拟身份验证器具有 一组属性。 这些属性在 Selenium 绑定中映射为 VirtualAuthenticatorOptions。
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
.setIsUserVerified(true)
.setHasUserVerification(true)
.setIsUserConsenting(true)
.setTransport(VirtualAuthenticatorOptions.Transport.USB)
.setProtocol(VirtualAuthenticatorOptions.Protocol.U2F)
.setHasResidentKey(false);
// Create virtual authenticator options
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
.SetIsUserVerified(true)
.SetHasUserVerification(true)
.SetIsUserConsenting(true)
.SetTransport(VirtualAuthenticatorOptions.Transport.USB)
.SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F)
.SetHasResidentKey(false);
it('Virtual options', async function () {
options = new VirtualAuthenticatorOptions();
options.setIsUserVerified(true);
options.setHasUserVerification(true);
options.setIsUserConsenting(true);
options.setTransport(Transport['USB']);
options.setProtocol(Protocol['U2F']);
它使用提供的属性创建一个新的虚拟身份验证器。
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
.setProtocol(VirtualAuthenticatorOptions.Protocol.U2F)
.setHasResidentKey(false);
VirtualAuthenticator authenticator =
((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options);
// Create virtual authenticator options
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
.SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F)
.SetHasResidentKey(false);
// Register a virtual authenticator
((WebDriver)driver).AddVirtualAuthenticator(options);
List<Credential> credentialList = ((WebDriver)driver).GetCredentials();
options.setProtocol(Protocol['U2F']);
options.setHasResidentKey(false);
// Register a virtual authenticator
await driver.addVirtualAuthenticator(options);
删除之前添加的虚拟身份验证器。
((HasVirtualAuthenticator) driver).removeVirtualAuthenticator(authenticator);
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
.SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F)
.SetHasResidentKey(false);
String virtualAuthenticatorId = ((WebDriver)driver).AddVirtualAuthenticator(options);
((WebDriver)driver).RemoveVirtualAuthenticator(virtualAuthenticatorId);
await driver.addVirtualAuthenticator(options);
await driver.removeVirtualAuthenticator();
使用给定的所需凭据 参数 创建一个永久(有状态的)凭据。
byte[] credentialId = {1, 2, 3, 4};
byte[] userHandle = {1};
Credential residentCredential = Credential.createResidentCredential(
credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0);
byte[] credentialId = { 1, 2, 3, 4 };
byte[] userHandle = { 1 };
Credential residentCredential = Credential.CreateResidentCredential(
credentialId, "localhost", base64EncodedPK, userHandle, 0);
使用给定的所需凭据 参数 创建一个常驻(无状态)凭据。
byte[] credentialId = {1, 2, 3, 4};
Credential nonResidentCredential = Credential.createNonResidentCredential(
credentialId, "localhost", ec256PrivateKey, /*signCount=*/0);
byte[] credentialId = { 1, 2, 3, 4 };
Credential nonResidentCredential = Credential.CreateNonResidentCredential(
credentialId, "localhost", base64EncodedEC256PK, 0);
向身份验证器注册凭据。
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
.setProtocol(VirtualAuthenticatorOptions.Protocol.U2F)
.setHasResidentKey(false);
VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options);
byte[] credentialId = {1, 2, 3, 4};
Credential nonResidentCredential = Credential.createNonResidentCredential(
credentialId, "localhost", ec256PrivateKey, /*signCount=*/0);
authenticator.addCredential(nonResidentCredential);
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
.SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F)
.SetHasResidentKey(false);
((WebDriver)driver).AddVirtualAuthenticator(options);
byte[] credentialId = { 1, 2, 3, 4 };
Credential nonResidentCredential = Credential.CreateNonResidentCredential(
credentialId, "localhost", base64EncodedEC256PK, 0);
((WebDriver)driver).AddCredential(nonResidentCredential);
返回身份验证者拥有的凭据列表。
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
.setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2)
.setHasResidentKey(true)
.setHasUserVerification(true)
.setIsUserVerified(true);
VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options);
byte[] credentialId = {1, 2, 3, 4};
byte[] userHandle = {1};
Credential residentCredential = Credential.createResidentCredential(
credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0);
authenticator.addCredential(residentCredential);
List<Credential> credentialList = authenticator.getCredentials();
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
.SetProtocol(Protocol.CTAP2)
.SetHasResidentKey(true)
.SetHasUserVerification(true)
.SetIsUserVerified(true);
((WebDriver)driver).AddVirtualAuthenticator(options);
byte[] credentialId = { 1, 2, 3, 4 };
byte[] userHandle = { 1 };
Credential residentCredential = Credential.CreateResidentCredential(
credentialId, "localhost", base64EncodedPK, userHandle, 0);
((WebDriver)driver).AddCredential(residentCredential);
List<Credential> credentialList = ((WebDriver)driver).GetCredentials();
根据传递的凭据ID从身份验证器中删除凭据。
((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions());
byte[] credentialId = { 1, 2, 3, 4 };
Credential nonResidentCredential = Credential.CreateNonResidentCredential(
credentialId, "localhost", base64EncodedEC256PK, 0);
((WebDriver)driver).AddCredential(nonResidentCredential);
((WebDriver)driver).RemoveCredential(credentialId);
VirtualAuthenticator authenticator =
((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions());
byte[] credentialId = {1, 2, 3, 4};
Credential credential = Credential.createNonResidentCredential(
credentialId, "localhost", rsaPrivateKey, 0);
authenticator.addCredential(credential);
authenticator.removeCredential(credentialId);
从身份验证器中删除所有凭据。
VirtualAuthenticator authenticator =
((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions());
byte[] credentialId = {1, 2, 3, 4};
Credential residentCredential = Credential.createNonResidentCredential(
credentialId, "localhost", rsaPrivateKey, /*signCount=*/0);
authenticator.addCredential(residentCredential);
authenticator.removeAllCredentials();
((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions());
byte[] credentialId = { 1, 2, 3, 4 };
Credential nonResidentCredential = Credential.CreateNonResidentCredential(
credentialId, "localhost", base64EncodedEC256PK, 0);
((WebDriver)driver).AddCredential(nonResidentCredential);
((WebDriver)driver).RemoveAllCredentials();
设置身份验证器是模拟用户验证成功还是失败。
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
.setIsUserVerified(true);
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
.SetIsUserVerified(true);
除了高级元素交互之外, Actions 接口 还提供了对指定输入设备 可以执行的确切操作的精细控制. Selenium为3种输入源提供了接口: 键盘设备的键输入, 鼠标, 笔或触摸设备的输入, 以及滚轮设备的滚轮输入 (在Selenium 4.2中引入). Selenium允许您构建分配给特定输入的独立操作命令, 会将他们链接在一起, 并调用关联的执行方法以一次执行它们.
在从遗留JSON Wire协议迁移到 新的W3C WebDriver协议的过程中, 低级的操作构建块变得特别详细. 它非常强大, 但每个输入设备都有多种使用方法, 如果您需要管理多个设备, 则负责确保他们之间的同步正确.
值得庆幸的是, 您可能不需要学习如何直接使用低级命令, 因为您可能要执行的几乎所有操作, 都已提供了相应的简便方法, 这些方法可以为您组合较低级别的命令. 请分别参阅相应的键盘, 鼠标, 笔 和滚轮 页面.
指针移动和滚轮滚动 允许用户设置操作的持续时间, 但有时您只需要在操作之间等待一下, 即可正常工作.
WebElement clickable = driver.findElement(By.id("clickable"));
new Actions(driver)
.moveToElement(clickable)
.pause(Duration.ofSeconds(1))
.clickAndHold()
.pause(Duration.ofSeconds(1))
.sendKeys("abc")
.perform();
clickable = driver.find_element(By.ID, "clickable")
ActionChains(driver)\
.move_to_element(clickable)\
.pause(1)\
.click_and_hold()\
.pause(1)\
.send_keys("abc")\
.perform()
IWebElement clickable = driver.FindElement(By.Id("clickable"));
new Actions(driver)
.MoveToElement(clickable)
.Pause(TimeSpan.FromSeconds(1))
.ClickAndHold()
.Pause(TimeSpan.FromSeconds(1))
.SendKeys("abc")
.Perform();
clickable = driver.find_element(id: 'clickable')
driver.action
.move_to(clickable)
.pause(duration: 1)
.click_and_hold
.pause(duration: 1)
.send_keys('abc')
.perform
const clickable = await driver.findElement(By.id('clickable'))
await driver.actions()
.move({ origin: clickable })
.pause(1000)
.press()
.pause(1000)
.sendKeys('abc')
.perform()
val clickable = driver.findElement(By.id("clickable"))
Actions(driver)
.moveToElement(clickable)
.pause(Duration.ofSeconds(1))
.clickAndHold()
.pause(Duration.ofSeconds(1))
.sendKeys("abc")
.perform()
需要注意的重要一点是, 驱动程序会记住整个会话中所有输入项的状态. 即使创建actions类的新实例, 按下的键和指针的位置 也将处于以前执行的操作离开它们的任何状态.
有一种特殊的方法来释放所有当前按下的键和指针按钮. 此方法在每种语言中的实现方式不同, 因为它不会使用perform方法执行.
((RemoteWebDriver) driver).resetInputState();
ActionBuilder(driver).clear_actions()
((WebDriver)driver).ResetInputState();
driver.action.release_actions
await driver.actions().clear()
(driver as RemoteWebDriver).resetInputState()
只有 2 个操作可以使用键盘完成: 按下某个键,以及释放一个按下的键. 除了支持 ASCII 字符外,每个键盘按键还具有 可以按特定顺序按下或释放的表现形式.
除了由常规unicode表示的按键, 其他键盘按键被分配了一些unicode值以用于操作Selenium 每种语言都有自己的方式来援引这些按键; 这里 可以找到完整列表
Use the Java Keys enum
Use the Python Keys class
Use the .NET static Keys class
Use the Ruby KEYS constant
Use the JavaScript KEYS constant
Use the Java Keys enum
new Actions(driver)
.keyDown(Keys.SHIFT)
.sendKeys("a")
.perform();
ActionChains(driver)\
.key_down(Keys.SHIFT)\
.send_keys("abc")\
.perform()
.KeyDown(Keys.Shift)
.SendKeys("a")
.Perform();
driver.action
.key_down(:shift)
.send_keys('a')
.perform
await driver.actions()
.keyDown(Key.SHIFT)
.sendKeys('a')
.perform()
Actions(driver)
.keyDown(Keys.SHIFT)
.sendKeys("a")
.perform()
new Actions(driver)
.keyDown(Keys.SHIFT)
.sendKeys("a")
.keyUp(Keys.SHIFT)
.sendKeys("b")
.perform();
ActionChains(driver)\
.key_down(Keys.SHIFT)\
.send_keys("a")\
.key_up(Keys.SHIFT)\
.send_keys("b")\
.perform()
new Actions(driver)
.KeyDown(Keys.Shift)
.SendKeys("a")
.KeyUp(Keys.Shift)
.SendKeys("b")
.Perform();
driver.action
.key_down(:shift)
.send_keys('a')
.key_up(:shift)
.send_keys('b')
.perform
await driver.actions()
.keyDown(Key.SHIFT)
.sendKeys('a')
.keyUp(Key.SHIFT)
.sendKeys('b')
.perform()
Actions(driver)
.keyDown(Keys.SHIFT)
.sendKeys("a")
.keyUp(Keys.SHIFT)
.sendKeys("b")
.perform()
这是Actions API的一种便捷方法, 它将 keyDown 和 keyUp 命令组合在一个操作中. 执行此命令与使用 element 方法略有不同, 但这主要用于,需要在其他操作之间键入多个字符时使用.
new Actions(driver)
.sendKeys("abc")
.perform();
ActionChains(driver)\
.send_keys("abc")\
.perform()
new Actions(driver)
.SendKeys("abc")
driver.action
.send_keys('abc')
.perform
const textField = driver.findElement(By.id('textInput'))
await textField.click()
Actions(driver)
.sendKeys("abc")
.perform()
new Actions(driver)
.sendKeys(textField, "Selenium!")
.perform();
text_input = driver.find_element(By.ID, "textInput")
ActionChains(driver)\
.send_keys_to_element(text_input, "abc")\
.perform()
driver.FindElement(By.TagName("body")).Click();
IWebElement textField = driver.FindElement(By.Id("textInput"));
new Actions(driver)
text_field = driver.find_element(id: 'textInput')
driver.action
.send_keys(text_field, 'Selenium!')
.perform
const textField = await driver.findElement(By.id('textInput'))
await driver.actions()
.sendKeys(textField, 'abc')
.perform()
val textField = driver.findElement(By.id("textInput"))
Actions(driver)
.sendKeys(textField, "Selenium!")
.perform()
下面是使用上述所有方法执行复制/粘贴操作的示例.
请注意, 用于此操作的键位会有所不同, 具体取决于它是否是 Mac OS.
此代码将以文本收尾: SeleniumSelenium!
Keys cmdCtrl = Platform.getCurrent().is(Platform.MAC) ? Keys.COMMAND : Keys.CONTROL;
WebElement textField = driver.findElement(By.id("textInput"));
new Actions(driver)
.sendKeys(textField, "Selenium!")
.sendKeys(Keys.ARROW_LEFT)
.keyDown(Keys.SHIFT)
.sendKeys(Keys.ARROW_UP)
.keyUp(Keys.SHIFT)
.keyDown(cmdCtrl)
.sendKeys("xvv")
.keyUp(cmdCtrl)
.perform();
Assertions.assertEquals("SeleniumSelenium!", textField.getAttribute("value"));
cmd_ctrl = Keys.COMMAND if sys.platform == 'darwin' else Keys.CONTROL
ActionChains(driver)\
.send_keys("Selenium!")\
.send_keys(Keys.ARROW_LEFT)\
.key_down(Keys.SHIFT)\
.send_keys(Keys.ARROW_UP)\
.key_up(Keys.SHIFT)\
.key_down(cmd_ctrl)\
.send_keys("xvv")\
.key_up(cmd_ctrl)\
.perform()
var capabilities = ((WebDriver)driver).Capabilities;
String platformName = (string)capabilities.GetCapability("platformName");
String cmdCtrl = platformName.Contains("mac") ? Keys.Command : Keys.Control;
new Actions(driver)
.SendKeys("Selenium!")
.SendKeys(Keys.ArrowLeft)
.KeyDown(Keys.Shift)
.SendKeys(Keys.ArrowUp)
cmd_ctrl = driver.capabilities.platform_name.include?('mac') ? :command : :control
driver.action
.send_keys('Selenium!')
.send_keys(:arrow_left)
.key_down(:shift)
.send_keys(:arrow_up)
.key_up(:shift)
.key_down(cmd_ctrl)
.send_keys('xvv')
.key_up(cmd_ctrl)
.perform
const cmdCtrl = platform.includes('darwin') ? Key.COMMAND : Key.CONTROL
await driver.actions()
.click(textField)
.sendKeys('Selenium!')
.sendKeys(Key.ARROW_LEFT)
.keyDown(Key.SHIFT)
.sendKeys(Key.ARROW_UP)
.keyUp(Key.SHIFT)
.keyDown(cmdCtrl)
.sendKeys('xvv')
.keyUp(cmdCtrl)
.perform()
val cmdCtrl = if(platformName == Platform.MAC) Keys.COMMAND else Keys.CONTROL
val textField = driver.findElement(By.id("textInput"))
Actions(driver)
.sendKeys(textField, "Selenium!")
.sendKeys(Keys.ARROW_LEFT)
.keyDown(Keys.SHIFT)
.sendKeys(Keys.ARROW_UP)
.keyUp(Keys.SHIFT)
.keyDown(cmdCtrl)
.sendKeys("xvv")
.keyUp(cmdCtrl)
.perform()
There are only 3 actions that can be accomplished with a mouse: pressing down on a button, releasing a pressed button, and moving the mouse. Selenium provides convenience methods that combine these actions in the most common ways.
This method combines moving the mouse to the center of an element with pressing the left mouse button. This is useful for focusing a specific element:
WebElement clickable = driver.findElement(By.id("clickable"));
new Actions(driver)
.clickAndHold(clickable)
.perform();
clickable = driver.find_element(By.ID, "clickable")
ActionChains(driver)\
.click_and_hold(clickable)\
.perform()
IWebElement clickable = driver.FindElement(By.Id("clickable"));
new Actions(driver)
.ClickAndHold(clickable)
.Perform();
clickable = driver.find_element(id: 'clickable')
driver.action
.click_and_hold(clickable)
.perform
let clickable = driver.findElement(By.id("clickable"));
const actions = driver.actions({async: true});
await actions.move({origin: clickable}).press().perform();
val clickable = driver.findElement(By.id("clickable"))
Actions(driver)
.clickAndHold(clickable)
.perform()
This method combines moving to the center of an element with pressing and releasing the left mouse button. This is otherwise known as “clicking”:
WebElement clickable = driver.findElement(By.id("click"));
new Actions(driver)
.click(clickable)
.perform();
clickable = driver.find_element(By.ID, "click")
ActionChains(driver)\
.click(clickable)\
.perform()
IWebElement clickable = driver.FindElement(By.Id("click"));
new Actions(driver)
.Click(clickable)
.Perform();
clickable = driver.find_element(id: 'click')
driver.action
.click(clickable)
.perform
let click = driver.findElement(By.id("click"));
const actions = driver.actions({async: true});
await actions.move({origin: click}).click().perform();
val clickable = driver.findElement(By.id("click"))
Actions(driver)
.click(clickable)
.perform()
There are a total of 5 defined buttons for a Mouse:
This method combines moving to the center of an element with pressing and releasing the right mouse button (button 2). This is otherwise known as “right-clicking”:
WebElement clickable = driver.findElement(By.id("clickable"));
new Actions(driver)
.contextClick(clickable)
.perform();
clickable = driver.find_element(By.ID, "clickable")
ActionChains(driver)\
.context_click(clickable)\
.perform()
IWebElement clickable = driver.FindElement(By.Id("clickable"));
new Actions(driver)
.ContextClick(clickable)
.Perform();
clickable = driver.find_element(id: 'clickable')
driver.action
.context_click(clickable)
.perform
const clickable = driver.findElement(By.id("clickable"));
const actions = driver.actions({async: true});
await actions.contextClick(clickable).perform();
val clickable = driver.findElement(By.id("clickable"))
Actions(driver)
.contextClick(clickable)
.perform()
There is no convenience method for this, it is just pressing and releasing mouse button 3
PointerInput mouse = new PointerInput(PointerInput.Kind.MOUSE, "default mouse");
Sequence actions = new Sequence(mouse, 0)
.addAction(mouse.createPointerDown(PointerInput.MouseButton.BACK.asArg()))
.addAction(mouse.createPointerUp(PointerInput.MouseButton.BACK.asArg()));
((RemoteWebDriver) driver).perform(Collections.singletonList(actions));
action = ActionBuilder(driver)
action.pointer_action.pointer_down(MouseButton.BACK)
action.pointer_action.pointer_up(MouseButton.BACK)
action.perform()
ActionBuilder actionBuilder = new ActionBuilder();
PointerInputDevice mouse = new PointerInputDevice(PointerKind.Mouse, "default mouse");
actionBuilder.AddAction(mouse.CreatePointerDown(MouseButton.Back));
actionBuilder.AddAction(mouse.CreatePointerUp(MouseButton.Back));
((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList());
driver.action
.pointer_down(:back)
.pointer_up(:back)
.perform
const actions = driver.actions({async: true});
await actions.press(Button.BACK).release(Button.BACK).perform()
val mouse = PointerInput(PointerInput.Kind.MOUSE, "default mouse")
val actions = Sequence(mouse, 0)
.addAction(mouse.createPointerDown(PointerInput.MouseButton.BACK.asArg()))
.addAction(mouse.createPointerUp(PointerInput.MouseButton.BACK.asArg()))
(driver as RemoteWebDriver).perform(Collections.singletonList(actions))
There is no convenience method for this, it is just pressing and releasing mouse button 4
PointerInput mouse = new PointerInput(PointerInput.Kind.MOUSE, "default mouse");
Sequence actions = new Sequence(mouse, 0)
.addAction(mouse.createPointerDown(PointerInput.MouseButton.FORWARD.asArg()))
.addAction(mouse.createPointerUp(PointerInput.MouseButton.FORWARD.asArg()));
((RemoteWebDriver) driver).perform(Collections.singletonList(actions));
action = ActionBuilder(driver)
action.pointer_action.pointer_down(MouseButton.FORWARD)
action.pointer_action.pointer_up(MouseButton.FORWARD)
action.perform()
ActionBuilder actionBuilder = new ActionBuilder();
PointerInputDevice mouse = new PointerInputDevice(PointerKind.Mouse, "default mouse");
actionBuilder.AddAction(mouse.CreatePointerDown(MouseButton.Forward));
actionBuilder.AddAction(mouse.CreatePointerUp(MouseButton.Forward));
((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList());
driver.action
.pointer_down(:forward)
.pointer_up(:forward)
.perform
const actions = driver.actions({async: true});
await actions.press(Button.FORWARD).release(Button.FORWARD).perform()
val mouse = PointerInput(PointerInput.Kind.MOUSE, "default mouse")
val actions = Sequence(mouse, 0)
.addAction(mouse.createPointerDown(PointerInput.MouseButton.FORWARD.asArg()))
.addAction(mouse.createPointerUp(PointerInput.MouseButton.FORWARD.asArg()))
(driver as RemoteWebDriver).perform(Collections.singletonList(actions))
This method combines moving to the center of an element with pressing and releasing the left mouse button twice.
WebElement clickable = driver.findElement(By.id("clickable"));
new Actions(driver)
.doubleClick(clickable)
.perform();
clickable = driver.find_element(By.ID, "clickable")
ActionChains(driver)\
.double_click(clickable)\
.perform()
IWebElement clickable = driver.FindElement(By.Id("clickable"));
new Actions(driver)
.DoubleClick(clickable)
.Perform();
clickable = driver.find_element(id: 'clickable')
driver.action
.double_click(clickable)
.perform
const clickable = driver.findElement(By.id("clickable"));
const actions = driver.actions({async: true});
await actions.doubleClick(clickable).perform();
val clickable = driver.findElement(By.id("clickable"))
Actions(driver)
.doubleClick(clickable)
.perform()
This method moves the mouse to the in-view center point of the element. This is otherwise known as “hovering.” Note that the element must be in the viewport or else the command will error.
WebElement hoverable = driver.findElement(By.id("hover"));
new Actions(driver)
.moveToElement(hoverable)
.perform();
hoverable = driver.find_element(By.ID, "hover")
ActionChains(driver)\
.move_to_element(hoverable)\
.perform()
IWebElement hoverable = driver.FindElement(By.Id("hover"));
new Actions(driver)
.MoveToElement(hoverable)
.Perform();
hoverable = driver.find_element(id: 'hover')
driver.action
.move_to(hoverable)
.perform
const hoverable = driver.findElement(By.id("hover"));
const actions = driver.actions({async: true});
await actions.move({origin: hoverable}).perform();
val hoverable = driver.findElement(By.id("hover"))
Actions(driver)
.moveToElement(hoverable)
.perform()
These methods first move the mouse to the designated origin and then by the number of pixels in the provided offset. Note that the position of the mouse must be in the viewport or else the command will error.
This method moves the mouse to the in-view center point of the element, then moves by the provided offset.
WebElement tracker = driver.findElement(By.id("mouse-tracker"));
new Actions(driver)
.moveToElement(tracker, 8, 0)
.perform();
mouse_tracker = driver.find_element(By.ID, "mouse-tracker")
ActionChains(driver)\
.move_to_element_with_offset(mouse_tracker, 8, 0)\
.perform()
IWebElement tracker = driver.FindElement(By.Id("mouse-tracker"));
new Actions(driver)
.MoveToElement(tracker, 8, 0)
.Perform();
mouse_tracker = driver.find_element(id: 'mouse-tracker')
driver.action
.move_to(mouse_tracker, 8, 11)
.perform
val tracker = driver.findElement(By.id("mouse-tracker"))
Actions(driver)
.moveToElement(tracker, 8, 0)
.perform()
This method moves the mouse from the upper left corner of the current viewport by the provided offset.
PointerInput mouse = new PointerInput(PointerInput.Kind.MOUSE, "default mouse");
Sequence actions = new Sequence(mouse, 0)
.addAction(mouse.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), 8, 12));
((RemoteWebDriver) driver).perform(Collections.singletonList(actions));
action = ActionBuilder(driver)
action.pointer_action.move_to_location(8, 0)
action.perform()
ActionBuilder actionBuilder = new ActionBuilder();
PointerInputDevice mouse = new PointerInputDevice(PointerKind.Mouse, "default mouse");
actionBuilder.AddAction(mouse.CreatePointerMove(CoordinateOrigin.Viewport,
8, 0, TimeSpan.Zero));
((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList());
driver.action
.move_to_location(8, 12)
.perform
const actions = driver.actions({async: true});
await actions.move({x: 8, y: 0}).perform();
val mouse = PointerInput(PointerInput.Kind.MOUSE, "default mouse")
val actions = Sequence(mouse, 0)
.addAction(mouse.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), 8, 12))
(driver as RemoteWebDriver).perform(Collections.singletonList(actions))
This method moves the mouse from its current position by the offset provided by the user. If the mouse has not previously been moved, the position will be in the upper left corner of the viewport. Note that the pointer position does not change when the page is scrolled.
Note that the first argument X specifies to move right when positive, while the second argument
Y specifies to move down when positive. So moveByOffset(30, -10)
moves right 30 and up 10 from
the current mouse position.
new Actions(driver)
.moveByOffset(13, 15)
.perform();
ActionChains(driver)\
.move_by_offset( 13, 15)\
.perform()
new Actions(driver)
.MoveByOffset(13, 15)
.Perform();
driver.action
.move_by(13, 15)
.perform
await actions.move({x: 13, y: 15, origin: Origin.POINTER}).perform()
Actions(driver)
.moveByOffset(13, 15)
.perform()
This method firstly performs a click-and-hold on the source element, moves to the location of the target element and then releases the mouse.
WebElement draggable = driver.findElement(By.id("draggable"));
WebElement droppable = driver.findElement(By.id("droppable"));
new Actions(driver)
.dragAndDrop(draggable, droppable)
.perform();
draggable = driver.find_element(By.ID, "draggable")
droppable = driver.find_element(By.ID, "droppable")
ActionChains(driver)\
.drag_and_drop(draggable, droppable)\
.perform()
IWebElement draggable = driver.FindElement(By.Id("draggable"));
IWebElement droppable = driver.FindElement(By.Id("droppable"));
new Actions(driver)
.DragAndDrop(draggable, droppable)
.Perform();
draggable = driver.find_element(id: 'draggable')
droppable = driver.find_element(id: 'droppable')
driver.action
.drag_and_drop(draggable, droppable)
.perform
const draggable = driver.findElement(By.id("draggable"));
const droppable = await driver.findElement(By.id("droppable"));
const actions = driver.actions({async: true});
await actions.dragAndDrop(draggable, droppable).perform();
val draggable = driver.findElement(By.id("draggable"))
val droppable = driver.findElement(By.id("droppable"))
Actions(driver)
.dragAndDrop(draggable, droppable)
.perform()
This method firstly performs a click-and-hold on the source element, moves to the given offset and then releases the mouse.
WebElement draggable = driver.findElement(By.id("draggable"));
Rectangle start = draggable.getRect();
Rectangle finish = driver.findElement(By.id("droppable")).getRect();
new Actions(driver)
.dragAndDropBy(draggable, finish.getX() - start.getX(), finish.getY() - start.getY())
.perform();
draggable = driver.find_element(By.ID, "draggable")
start = draggable.location
finish = driver.find_element(By.ID, "droppable").location
ActionChains(driver)\
.drag_and_drop_by_offset(draggable, finish['x'] - start['x'], finish['y'] - start['y'])\
.perform()
IWebElement draggable = driver.FindElement(By.Id("draggable"));
Point start = draggable.Location;
Point finish = driver.FindElement(By.Id("droppable")).Location;
new Actions(driver)
.DragAndDropToOffset(draggable, finish.X - start.X, finish.Y - start.Y)
.Perform();
draggable = driver.find_element(id: 'draggable')
start = draggable.rect
finish = driver.find_element(id: 'droppable').rect
driver.action
.drag_and_drop_by(draggable, finish.x - start.x, finish.y - start.y)
.perform
const draggable = driver.findElement(By.id("draggable"));
let start = await draggable.getRect();
let finish = await driver.findElement(By.id("droppable")).getRect();
const actions = driver.actions({async: true});
await actions.dragAndDrop(draggable, {x: finish.x - start.x, y: finish.y - start.y}).perform();
val draggable = driver.findElement(By.id("draggable"))
val start = draggable.getRect()
val finish = driver.findElement(By.id("droppable")).getRect()
Actions(driver)
.dragAndDropBy(draggable, finish.getX() - start.getX(), finish.getY() - start.getY())
.perform()
A Pen is a type of pointer input that has most of the same behavior as a mouse, but can also have event properties unique to a stylus. Additionally, while a mouse has 5 buttons, a pen has 3 equivalent button states:
WebElement pointerArea = driver.findElement(By.id("pointerArea"));
new Actions(driver)
.setActivePointer(PointerInput.Kind.PEN, "default pen")
.moveToElement(pointerArea)
.clickAndHold()
.moveByOffset(2, 2)
.release()
.perform();
pointer_area = driver.find_element(By.ID, "pointerArea")
pen_input = PointerInput(POINTER_PEN, "default pen")
action = ActionBuilder(driver, mouse=pen_input)
action.pointer_action\
.move_to(pointer_area)\
.pointer_down()\
.move_by(2, 2)\
.pointer_up()
action.perform()
IWebElement pointerArea = driver.FindElement(By.Id("pointerArea"));
ActionBuilder actionBuilder = new ActionBuilder();
PointerInputDevice pen = new PointerInputDevice(PointerKind.Pen, "default pen");
actionBuilder.AddAction(pen.CreatePointerMove(pointerArea, 0, 0, TimeSpan.FromMilliseconds(800)));
actionBuilder.AddAction(pen.CreatePointerDown(MouseButton.Left));
actionBuilder.AddAction(pen.CreatePointerMove(CoordinateOrigin.Pointer,
2, 2, TimeSpan.Zero));
actionBuilder.AddAction(pen.CreatePointerUp(MouseButton.Left));
((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList());
pointer_area = driver.find_element(id: 'pointerArea')
driver.action(devices: :pen)
.move_to(pointer_area)
.pointer_down
.move_by(2, 2)
.pointer_up
.perform
val pointerArea = driver.findElement(By.id("pointerArea"))
Actions(driver)
.setActivePointer(PointerInput.Kind.PEN, "default pen")
.moveToElement(pointerArea)
.clickAndHold()
.moveByOffset(2, 2)
.release()
.perform()
WebElement pointerArea = driver.findElement(By.id("pointerArea"));
PointerInput pen = new PointerInput(PointerInput.Kind.PEN, "default pen");
PointerInput.PointerEventProperties eventProperties = PointerInput.eventProperties()
.setTiltX(-72)
.setTiltY(9)
.setTwist(86);
PointerInput.Origin origin = PointerInput.Origin.fromElement(pointerArea);
Sequence actionListPen = new Sequence(pen, 0)
.addAction(pen.createPointerMove(Duration.ZERO, origin, 0, 0))
.addAction(pen.createPointerDown(0))
.addAction(pen.createPointerMove(Duration.ZERO, origin, 2, 2, eventProperties))
.addAction(pen.createPointerUp(0));
((RemoteWebDriver) driver).perform(Collections.singletonList(actionListPen));
pointer_area = driver.find_element(By.ID, "pointerArea")
pen_input = PointerInput(POINTER_PEN, "default pen")
action = ActionBuilder(driver, mouse=pen_input)
action.pointer_action\
.move_to(pointer_area)\
.pointer_down()\
.move_by(2, 2, tilt_x=-72, tilt_y=9, twist=86)\
.pointer_up(0)
action.perform()
IWebElement pointerArea = driver.FindElement(By.Id("pointerArea"));
ActionBuilder actionBuilder = new ActionBuilder();
PointerInputDevice pen = new PointerInputDevice(PointerKind.Pen, "default pen");
PointerInputDevice.PointerEventProperties properties = new PointerInputDevice.PointerEventProperties() {
TiltX = -72,
TiltY = 9,
Twist = 86,
};
actionBuilder.AddAction(pen.CreatePointerMove(pointerArea, 0, 0, TimeSpan.FromMilliseconds(800)));
actionBuilder.AddAction(pen.CreatePointerDown(MouseButton.Left));
actionBuilder.AddAction(pen.CreatePointerMove(CoordinateOrigin.Pointer,
2, 2, TimeSpan.Zero, properties));
actionBuilder.AddAction(pen.CreatePointerUp(MouseButton.Left));
((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList());
pointer_area = driver.find_element(id: 'pointerArea')
driver.action(devices: :pen)
.move_to(pointer_area)
.pointer_down
.move_by(2, 2, tilt_x: -72, tilt_y: 9, twist: 86)
.pointer_up
.perform
val pointerArea = driver.findElement(By.id("pointerArea"))
val pen = PointerInput(PointerInput.Kind.PEN, "default pen")
val eventProperties = PointerInput.eventProperties()
.setTiltX(-72)
.setTiltY(9)
.setTwist(86)
val origin = PointerInput.Origin.fromElement(pointerArea)
val actionListPen = Sequence(pen, 0)
.addAction(pen.createPointerMove(Duration.ZERO, origin, 0, 0))
.addAction(pen.createPointerDown(0))
.addAction(pen.createPointerMove(Duration.ZERO, origin, 2, 2, eventProperties))
.addAction(pen.createPointerUp(0))
(driver as RemoteWebDriver).perform(listOf(actionListPen))
There are 5 scenarios for scrolling on a page.
This is the most common scenario. Unlike traditional click and send keys methods, the actions class does not automatically scroll the target element into view, so this method will need to be used if elements are not already inside the viewport.
This method takes a web element as the sole argument.
Regardless of whether the element is above or below the current viewscreen, the viewport will be scrolled so the bottom of the element is at the bottom of the screen.
WebElement iframe = driver.findElement(By.tagName("iframe"));
new Actions(driver)
.scrollToElement(iframe)
.perform();
iframe = driver.find_element(By.TAG_NAME, "iframe")
ActionChains(driver)\
.scroll_to_element(iframe)\
.perform()
IWebElement iframe = driver.FindElement(By.TagName("iframe"));
new Actions(driver)
.ScrollToElement(iframe)
.Perform();
iframe = driver.find_element(tag_name: 'iframe')
driver.action
.scroll_to(iframe)
.perform
const iframe = await driver.findElement(By.css("iframe"))
await driver.actions()
.scroll(0, 0, 0, 0, iframe)
.perform()
val iframe = driver.findElement(By.tagName("iframe"))
Actions(driver)
.scrollToElement(iframe)
.perform()
This is the second most common scenario for scrolling. Pass in an delta x and a delta y value for how much to scroll in the right and down directions. Negative values represent left and up, respectively.
WebElement footer = driver.findElement(By.tagName("footer"));
int deltaY = footer.getRect().y;
new Actions(driver)
.scrollByAmount(0, deltaY)
.perform();
footer = driver.find_element(By.TAG_NAME, "footer")
delta_y = footer.rect['y']
ActionChains(driver)\
.scroll_by_amount(0, delta_y)\
.perform()
IWebElement footer = driver.FindElement(By.TagName("footer"));
int deltaY = footer.Location.Y;
new Actions(driver)
.ScrollByAmount(0, deltaY)
.Perform();
footer = driver.find_element(tag_name: 'footer')
delta_y = footer.rect.y
driver.action
.scroll_by(0, delta_y)
.perform
const footer = await driver.findElement(By.css("footer"))
const deltaY = (await footer.getRect()).y
await driver.actions()
.scroll(0, 0, 0, deltaY)
.perform()
val footer = driver.findElement(By.tagName("footer"))
val deltaY = footer.getRect().y
Actions(driver)
.scrollByAmount(0, deltaY)
.perform()
This scenario is effectively a combination of the above two methods.
To execute this use the “Scroll From” method, which takes 3 arguments. The first represents the origination point, which we designate as the element, and the second two are the delta x and delta y values.
If the element is out of the viewport, it will be scrolled to the bottom of the screen, then the page will be scrolled by the provided delta x and delta y values.
WebElement iframe = driver.findElement(By.tagName("iframe"));
WheelInput.ScrollOrigin scrollOrigin = WheelInput.ScrollOrigin.fromElement(iframe);
new Actions(driver)
.scrollFromOrigin(scrollOrigin, 0, 200)
.perform();
iframe = driver.find_element(By.TAG_NAME, "iframe")
scroll_origin = ScrollOrigin.from_element(iframe)
ActionChains(driver)\
.scroll_from_origin(scroll_origin, 0, 200)\
.perform()
IWebElement iframe = driver.FindElement(By.TagName("iframe"));
WheelInputDevice.ScrollOrigin scrollOrigin = new WheelInputDevice.ScrollOrigin
{
Element = iframe
};
new Actions(driver)
.ScrollFromOrigin(scrollOrigin, 0, 200)
.Perform();
iframe = driver.find_element(tag_name: 'iframe')
scroll_origin = Selenium::WebDriver::WheelActions::ScrollOrigin.element(iframe)
driver.action
.scroll_from(scroll_origin, 0, 200)
.perform
const iframe = await driver.findElement(By.css("iframe"))
await driver.actions()
.scroll(0, 0, 0, 200, iframe)
.perform()
val iframe = driver.findElement(By.tagName("iframe"))
val scrollOrigin = WheelInput.ScrollOrigin.fromElement(iframe)
Actions(driver)
.scrollFromOrigin(scrollOrigin, 0, 200)
.perform()
This scenario is used when you need to scroll only a portion of the screen, and it is outside the viewport. Or is inside the viewport and the portion of the screen that must be scrolled is a known offset away from a specific element.
This uses the “Scroll From” method again, and in addition to specifying the element, an offset is specified to indicate the origin point of the scroll. The offset is calculated from the center of the provided element.
If the element is out of the viewport, it first will be scrolled to the bottom of the screen, then the origin of the scroll will be determined by adding the offset to the coordinates of the center of the element, and finally the page will be scrolled by the provided delta x and delta y values.
Note that if the offset from the center of the element falls outside of the viewport, it will result in an exception.
WebElement footer = driver.findElement(By.tagName("footer"));
WheelInput.ScrollOrigin scrollOrigin = WheelInput.ScrollOrigin.fromElement(footer, 0, -50);
new Actions(driver)
.scrollFromOrigin(scrollOrigin,0, 200)
.perform();
footer = driver.find_element(By.TAG_NAME, "footer")
scroll_origin = ScrollOrigin.from_element(footer, 0, -50)
ActionChains(driver)\
.scroll_from_origin(scroll_origin, 0, 200)\
.perform()
IWebElement footer = driver.FindElement(By.TagName("footer"));
var scrollOrigin = new WheelInputDevice.ScrollOrigin
{
Element = footer,
XOffset = 0,
YOffset = -50
};
new Actions(driver)
.ScrollFromOrigin(scrollOrigin, 0, 200)
.Perform();
footer = driver.find_element(tag_name: 'footer')
scroll_origin = Selenium::WebDriver::WheelActions::ScrollOrigin.element(footer, 0, -50)
driver.action
.scroll_from(scroll_origin, 0, 200)
.perform
const footer = await driver.findElement(By.css("footer"))
await driver.actions()
.scroll(0, -50, 0, 200, footer)
.perform()
val footer = driver.findElement(By.tagName("footer"))
val scrollOrigin = WheelInput.ScrollOrigin.fromElement(footer, 0, -50)
Actions(driver)
.scrollFromOrigin(scrollOrigin,0, 200)
.perform()
The final scenario is used when you need to scroll only a portion of the screen, and it is already inside the viewport.
This uses the “Scroll From” method again, but the viewport is designated instead of an element. An offset is specified from the upper left corner of the current viewport. After the origin point is determined, the page will be scrolled by the provided delta x and delta y values.
Note that if the offset from the upper left corner of the viewport falls outside of the screen, it will result in an exception.
WheelInput.ScrollOrigin scrollOrigin = WheelInput.ScrollOrigin.fromViewport(10, 10);
new Actions(driver)
.scrollFromOrigin(scrollOrigin, 0, 200)
.perform();
scroll_origin = ScrollOrigin.from_viewport(10, 10)
ActionChains(driver)\
.scroll_from_origin(scroll_origin, 0, 200)\
.perform()
var scrollOrigin = new WheelInputDevice.ScrollOrigin
{
Viewport = true,
XOffset = 10,
YOffset = 10
};
new Actions(driver)
.ScrollFromOrigin(scrollOrigin, 0, 200)
.Perform();
scroll_origin = Selenium::WebDriver::WheelActions::ScrollOrigin.viewport(10, 10)
driver.action
.scroll_from(scroll_origin, 0, 200)
.perform
await driver.actions()
.scroll(10, 10, 0, 200)
.perform()
val scrollOrigin = WheelInput.ScrollOrigin.fromViewport(10, 10)
Actions(driver)
.scrollFromOrigin(scrollOrigin, 0, 200)
.perform()
Selenium正在与浏览器供应商合作创建 WebDriver双向协议 , 作为一种提供稳定的跨浏览器API的方法, 该API使用双向协议处理 各种浏览器的通用自动化以及特定测试的需求. 在此之前, 寻求此功能的用户 必须忍受当前实现的全部问题和局限.
严格限制请求响应命令的传统WebDriver模型, 将从user agent转变为基于WebSockets的软件控制, 通过这样完善流事件的能力, 以便更好地匹配浏览器DOM的事件性质.
因为将测试受限于特定浏览器的特定版本是个坏主意, Selenium项目建议尽可能使用WebDriver BiDi. 然而, 在规范完成之前, CDP提供了许多有用的东西. 为了帮助保持测试的独立性和可移植性, Selenium提供了一些有用的辅助类. 目前, 这些应用程序使用CDP, 但我们将尽快提供WebDriver Bidi的实现.
虽然Selenium 4提供了对Chrome DevTools Protocol (CDP) 的直接访问, 但是仍非常鼓励您使用 WebDriver Bidi APIs 代替.
许多浏览器都提供"开发工具" – 一组与浏览器集成的工具, 开发人员可以用其调试web应用程序并探索其页面的性能. 谷歌浏览器开发工具 使用一种称为Chrome DevTools Protocol (简称"CDP") 的协议. 顾名思义, 这不是为测试而设计的, 而并没有一个稳定的API, 所以它的功能高度依赖于浏览器的版本.
WebDriver Bidi是W3C WebDriver的下一代协议, 旨在提供由所有浏览器实现稳定的API, 但尚未完成. 在此之前, Selenium提供了通过CDP实现的方式 (诸如Google Chrome或Microsoft Edge, 以及Firefox), 允许您以有趣的方式增强测试. 下面给出了实际使用的例子.
一些应用程序在不同的位置具有不同的特性和功能. 自动化此类应用程序很难, 因为很难使用Selenium在浏览器中模拟地理位置. 但是在Devtools的帮助下, 我们可以轻易模拟他们. 下面的代码片段演示了这一点.
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
devTools.send(Emulation.setGeolocationOverride(Optional.of(52.5043),
Optional.of(13.4501),
Optional.of(1)));
driver.get("https://my-location.org/");
driver.quit();
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
def geoLocationTest():
driver = webdriver.Chrome()
Map_coordinates = dict({
"latitude": 41.8781,
"longitude": -87.6298,
"accuracy": 100
})
driver.execute_cdp_cmd("Emulation.setGeolocationOverride", Map_coordinates)
driver.get("<your site url>")
using System.Threading.Tasks;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.DevTools;
// Replace the version to match the Chrome version
using OpenQA.Selenium.DevTools.V87.Emulation;
namespace dotnet_test {
class Program {
public static void Main(string[] args) {
GeoLocation().GetAwaiter().GetResult();
}
public static async Task GeoLocation() {
ChromeDriver driver = new ChromeDriver();
DevToolsSession devToolsSession = driver.CreateDevToolsSession();
var geoLocationOverrideCommandSettings = new SetGeolocationOverrideCommandSettings();
geoLocationOverrideCommandSettings.Latitude = 51.507351;
geoLocationOverrideCommandSettings.Longitude = -0.127758;
geoLocationOverrideCommandSettings.Accuracy = 1;
await devToolsSession
.GetVersionSpecificDomains<OpenQA.Selenium.DevTools.V87.DevToolsSessionDomains>()
.Emulation
.SetGeolocationOverride(geoLocationOverrideCommandSettings);
driver.Url = "<your site url>";
}
}
}
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
# Latitude and longitude of Tokyo, Japan
coordinates = { latitude: 35.689487,
longitude: 139.691706,
accuracy: 100 }
driver.execute_cdp('Emulation.setGeolocationOverride', coordinates)
driver.get 'https://www.google.com/search?q=selenium'
ensure
driver.quit
end
const { By, Key, Browser} = require('selenium-webdriver');
const { suite } = require('selenium-webdriver/testing');
const assert = require("assert");
suite(function(env) {
describe('Emulate geolocation', function() {
let driver;
before(async function() {
driver = await env.builder().build();
});
after(() => driver.quit());
it('Emulate coordinates of Tokyo', async function() {
const cdpConnection = await driver.createCDPConnection('page');
// Latitude and longitude of Tokyo, Japan
const coordinates = {
latitude: 35.689487,
longitude: 139.691706,
accuracy: 100,
};
await cdpConnection.execute(
"Emulation.setGeolocationOverride",
coordinates
);
await driver.get("https://kawasaki-india.com/dealer-locator/");
});
});
},{ browsers: [Browser.CHROME, Browser.FIREFOX]});
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.devtools.DevTools
fun main() {
val driver = ChromeDriver()
val coordinates : HashMap<String, Any> = HashMap<String, Any> ()
coordinates.put("latitude", 50.2334)
coordinates.put("longitude", 0.2334)
coordinates.put("accuracy", 1)
driver.executeCdpCommand("Emulation.setGeolocationOverride", coordinates)
driver.get("https://www.google.com")
}
ChromeOptions chromeOptions = new ChromeOptions();
WebDriver driver = new RemoteWebDriver(new URL("<grid-url>"), chromeOptions);
driver = new Augmenter().augment(driver);
DevTools devTools = ((HasDevTools) driver).getDevTools();
devTools.createSession();
devTools.send(Emulation.setGeolocationOverride(Optional.of(52.5043),
Optional.of(13.4501),
Optional.of(1)));
driver.get("https://my-location.org/");
driver.quit();
from selenium import webdriver
#Replace the version to match the Chrome version
import selenium.webdriver.common.devtools.v93 as devtools
async def geoLocationTest():
chrome_options = webdriver.ChromeOptions()
driver = webdriver.Remote(
command_executor='<grid-url>',
options=chrome_options
)
async with driver.bidi_connection() as session:
cdpSession = session.session
await cdpSession.execute(devtools.emulation.set_geolocation_override(latitude=41.8781,longitude=-87.6298,accuracy=100))
driver.get("https://my-location.org/")
driver.quit()
using System.Threading.Tasks;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.DevTools;
// Replace the version to match the Chrome version
using OpenQA.Selenium.DevTools.V87.Emulation;
namespace dotnet_test {
class Program {
public static void Main(string[] args) {
GeoLocation().GetAwaiter().GetResult();
}
public static async Task GeoLocation() {
ChromeOptions chromeOptions = new ChromeOptions();
RemoteWebDriver driver = new RemoteWebDriver(new Uri("<grid-url>"), chromeOptions);
DevToolsSession devToolsSession = driver.CreateDevToolsSession();
var geoLocationOverrideCommandSettings = new SetGeolocationOverrideCommandSettings();
geoLocationOverrideCommandSettings.Latitude = 51.507351;
geoLocationOverrideCommandSettings.Longitude = -0.127758;
geoLocationOverrideCommandSettings.Accuracy = 1;
await devToolsSession
.GetVersionSpecificDomains<OpenQA.Selenium.DevTools.V87.DevToolsSessionDomains>()
.Emulation
.SetGeolocationOverride(geoLocationOverrideCommandSettings);
driver.Url = "https://my-location.org/";
}
}
}
driver = Selenium::WebDriver.for(
:remote,
:url => "<grid-url>",
:capabilities => :chrome)
begin
# Latitude and longitude of Tokyo, Japan
coordinates = { latitude: 35.689487,
longitude: 139.691706,
accuracy: 100 }
devToolsSession = driver.devtools
devToolsSession.send_cmd('Emulation.setGeolocationOverride', coordinates)
driver.get 'https://my-location.org/'
puts res
ensure
driver.quit
end
const webdriver = require('selenium-webdriver');
const BROWSER_NAME = webdriver.Browser.CHROME;
async function getDriver() {
return new webdriver.Builder()
.usingServer('<grid-url>')
.forBrowser(BROWSER_NAME)
.build();
}
async function executeCDPCommands () {
let driver = await getDriver();
await driver.get("<your site url>");
const cdpConnection = await driver.createCDPConnection('page');
//Latitude and longitude of Tokyo, Japan
const coordinates = {
latitude: 35.689487,
longitude: 139.691706,
accuracy: 100,
};
await cdpConnection.execute(
"Emulation.setGeolocationOverride",
coordinates
);
await driver.quit();
}
executeCDPCommands();
import org.openqa.selenium.WebDriver
import org.openqa.selenium.chrome.ChromeOptions
import org.openqa.selenium.devtools.HasDevTools
// Replace the version to match the Chrome version
import org.openqa.selenium.devtools.v91.emulation.Emulation
import org.openqa.selenium.remote.Augmenter
import org.openqa.selenium.remote.RemoteWebDriver
import java.net.URL
import java.util.Optional
fun main() {
val chromeOptions = ChromeOptions()
var driver: WebDriver = RemoteWebDriver(URL("<grid-url>"), chromeOptions)
driver = Augmenter().augment(driver)
val devTools = (driver as HasDevTools).devTools
devTools.createSession()
devTools.send(
Emulation.setGeolocationOverride(
Optional.of(52.5043),
Optional.of(13.4501),
Optional.of(1)
)
)
driver["https://my-location.org/"]
driver.quit()
}
使用Selenium与CDP的集成, 可以覆盖当前设备模式并模拟新模式. Width, height, mobile和deviceScaleFactor是必需的参数. 可选参数包括scale, screenWidth, screenHeight, positionX, positionY, dontSetVisible, screenOrientation, viewport和displayFeature.
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
// iPhone 11 Pro dimensions
devTools.send(Emulation.setDeviceMetricsOverride(375,
812,
50,
true,
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty()));
driver.get("https://selenium.dev/");
driver.quit();
from selenium import webdriver
driver = webdriver.Chrome()
// iPhone 11 Pro dimensions
set_device_metrics_override = dict({
"width": 375,
"height": 812,
"deviceScaleFactor": 50,
"mobile": True
})
driver.execute_cdp_cmd('Emulation.setDeviceMetricsOverride', set_device_metrics_override)
driver.get("<your site url>")
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.DevTools;
using System.Threading.Tasks;
using OpenQA.Selenium.DevTools.V91.Emulation;
using DevToolsSessionDomains = OpenQA.Selenium.DevTools.V91.DevToolsSessionDomains;
namespace Selenium4Sample {
public class ExampleDevice {
protected IDevToolsSession session;
protected IWebDriver driver;
protected DevToolsSessionDomains devToolsSession;
public async Task DeviceModeTest() {
ChromeOptions chromeOptions = new ChromeOptions();
//Set ChromeDriver
driver = new ChromeDriver();
//Get DevTools
IDevTools devTools = driver as IDevTools;
//DevTools Session
session = devTools.GetDevToolsSession();
var deviceModeSetting = new SetDeviceMetricsOverrideCommandSettings();
deviceModeSetting.Width = 600;
deviceModeSetting.Height = 1000;
deviceModeSetting.Mobile = true;
deviceModeSetting.DeviceScaleFactor = 50;
await session
.GetVersionSpecificDomains < OpenQA.Selenium.DevTools.V91.DevToolsSessionDomains > ()
.Emulation
.SetDeviceMetricsOverride(deviceModeSetting);
driver.Url = "<your site url>";
}
}
}
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
metrics = { width: 300,
height: 200,
mobile: true,
deviceScaleFactor: 50 }
driver.execute_cdp('Emulation.setDeviceMetricsOverride', metrics)
driver.get 'https://www.google.com'
ensure
driver.quit
end
const {Builder} = require('selenium-webdriver');
const firefox = require('selenium-webdriver/firefox');
const options = new firefox.Options();
// enable debugger for CDP
options.enableDebugger();
(async function example() {
try {
let driver = await new Builder().forBrowser('firefox').setFirefoxOptions(options).build();
const pageCdpConnection = await driver.createCDPConnection('page');
const metrics = {
width: 300,
height: 200,
deviceScaleFactor: 50,
mobile: true,
};
await pageCdpConnection.execute(
"Emulation.setDeviceMetricsOverride",
metrics
);
await driver.get("https://www.google.com");
await driver.quit();
} catch (e) {
console.log(e);
}
})();
fun kotlinOverridDeviceMode() {
val driver = ChromeDriver()
val deviceMetrics: Map<String, Any> = object : HashMap<String, Any>() {
init {
put("width", 600)
put("height", 1000)
put("mobile", true)
put("deviceScaleFactor", 50)
}
}
driver.executeCdpCommand("Emulation.setDeviceMetricsOverride", deviceMetrics)
driver.get("https://www.google.com")
driver.quit()
}
Collect various performance metrics while navigating the application.
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
public void performanceMetricsExample() {
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
devTools.send(Performance.enable(Optional.empty()));
List<Metric> metricList = devTools.send(Performance.getMetrics());
driver.get("https://google.com");
driver.quit();
for(Metric m : metricList) {
System.out.println(m.getName() + " = " + m.getValue());
}
}
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://www.duckduckgo.com')
driver.execute_cdp_cmd('Performance.enable', {})
t = driver.execute_cdp_cmd('Performance.getMetrics', {})
print(t)
driver.quit()
// File must contain the following using statements
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.DevTools;
// We must use a version-specific set of domains
using OpenQA.Selenium.DevTools.V94.Performance;
public async Task PerformanceMetricsExample()
{
IWebDriver driver = new ChromeDriver();
IDevTools devTools = driver as IDevTools;
DevToolsSession session = devTools.GetDevToolsSession();
await session.SendCommand<EnableCommandSettings>(new EnableCommandSettings());
var metricsResponse =
await session.SendCommand<GetMetricsCommandSettings, GetMetricsCommandResponse>(
new GetMetricsCommandSettings());
driver.Navigate().GoToUrl("http://www.google.com");
driver.Quit();
var metrics = metricsResponse.Metrics;
foreach (Metric metric in metrics)
{
Console.WriteLine("{0} = {1}", metric.Name, metric.Value);
}
}
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.get 'https://www.duckduckgo.com'
driver.execute_cdp('Performance.enable', {})
metrics = driver.execute_cdp('Performance.getMetrics', {})
puts metrics
ensure
driver.quit
end
await driver.get("https://www.duckduckgo.com");
await driver.sendAndGetDevToolsCommand('Performance.enable')
let result = await driver.sendAndGetDevToolsCommand('Performance.getMetrics')
console.log(result)
await driver.quit();
val driver = ChromeDriver()
val devTools = driver.devTools
devTools.createSession()
devTools.send(Performance.enable(Optional.empty()))
val metricList: List<Metric> = devTools.send(Performance.getMetrics())
driver["https://google.com"]
driver.quit()
for (m in metricList) {
println(m.name.toString() + " = " + m.value)
}
Page being translated from English to Chinese. Do you speak Chinese? Help us to translate it by sending us pull requests!
The following list of APIs will be growing as the Selenium project works through supporting real world use cases. If there is additional functionality you’d like to see, please raise a feature request.
Some applications make use of browser authentication to secure pages. With Selenium, you can automate the input of basic auth credentials whenever they arise.
Predicate<URI> uriPredicate = uri -> uri.getHost().contains("your-domain.com");
((HasAuthentication) driver).register(uriPredicate, UsernameAndPassword.of("admin", "password"));
driver.get("https://your-domain.com/login");
var handler = new NetworkAuthenticationHandler()
{
UriMatcher = _ => true,
Credentials = new PasswordCredentials("admin", "admin")
};
INetwork networkInterceptor = driver.Manage().Network;
networkInterceptor.AddAuthenticationHandler(handler);
await networkInterceptor.StartMonitoring();
driver.Navigate().GoToUrl("https://the-internet.herokuapp.com/basic_auth");
await networkInterceptor.StopMonitoring();
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.devtools.new
driver.register(username: 'username', password: 'password')
driver.get '<your site url>'
ensure
driver.quit
end
const {Builder} = require('selenium-webdriver');
(async function example() {
try {
let driver = await new Builder()
.forBrowser('chrome')
.build();
const pageCdpConnection = await driver.createCDPConnection('page');
await driver.register('username', 'password', pageCdpConnection);
await driver.get('https://the-internet.herokuapp.com/basic_auth');
await driver.quit();
}catch (e){
console.log(e)
}
}())
val uriPredicate = Predicate { uri: URI ->
uri.host.contains("your-domain.com")
}
(driver as HasAuthentication).register(uriPredicate, UsernameAndPassword.of("admin", "password"))
driver.get("https://your-domain.com/login")
Mutation Observation is the ability to capture events via WebDriver BiDi when there are DOM mutations on a specific element in the DOM.
ChromeDriver driver = new ChromeDriver();
AtomicReference<DomMutationEvent> seen = new AtomicReference<>();
CountDownLatch latch = new CountDownLatch(1);
((HasLogEvents) driver).onLogEvent(domMutation(mutation -> {
seen.set(mutation);
latch.countDown();
}));
driver.get("https://www.google.com");
WebElement span = driver.findElement(By.cssSelector("span"));
((JavascriptExecutor) driver).executeScript("arguments[0].setAttribute('cheese', 'gouda');", span);
assertThat(latch.await(10, SECONDS), is(true));
assertThat(seen.get().getAttributeName(), is("cheese"));
assertThat(seen.get().getCurrentValue(), is("gouda"));
driver.quit();
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
driver = webdriver.Chrome()
async with driver.log.mutation_events() as event:
pages.load("dynamic.html")
driver.find_element(By.ID, "reveal").click()
WebDriverWait(driver, 5)\
.until(EC.visibility_of(driver.find_element(By.ID, "revealed")))
assert event["attribute_name"] == "style"
assert event["current_value"] == ""
assert event["old_value"] == "display:none;"
List<DomMutationData> attributeValueChanges = new List<DomMutationData>();
DefaultWait<List<DomMutationData>> wait = new DefaultWait<List<DomMutationData>>(attributeValueChanges);
wait.Timeout = TimeSpan.FromSeconds(3);
using IJavaScriptEngine monitor = new JavaScriptEngine(driver);
monitor.DomMutated += (sender, e) =>
{
attributeValueChanges.Add(e.AttributeData);
};
await monitor.StartEventMonitoring();
driver.Navigate().GoToUrl("http://www.google.com");
IWebElement span = driver.FindElement(By.CssSelector("span"));
await monitor.EnableDomMutationMonitoring();
((IJavaScriptExecutor) driver).ExecuteScript("arguments[0].setAttribute('cheese', 'gouda');", span);
wait.Until((list) => list.Count > 0);
Console.WriteLine("Found {0} DOM mutation events", attributeValueChanges.Count);
foreach(var record in attributeValueChanges)
{
Console.WriteLine("Attribute name: {0}", record.AttributeName);
Console.WriteLine("Attribute value: {0}", record.AttributeValue);
}
await monitor.DisableDomMutationMonitoring();
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :firefox
begin
driver.on_log_event(:mutation) { |mutation| mutations.push(mutation) }
driver.navigate.to url_for('dynamic.html')
driver.find_element(id: 'reveal').click
wait.until { mutations.any? }
mutation = mutations.first
expect(mutation.element).to eq(driver.find_element(id: 'revealed'))
expect(mutation.attribute_name).to eq('style')
expect(mutation.current_value).to eq('')
expect(mutation.old_value).to eq('display:none;')
ensure
driver.quit
end
const {Builder, until} = require('selenium-webdriver');
const assert = require("assert");
(async function example() {
try {
let driver = await new Builder()
.forBrowser('chrome')
.build();
const cdpConnection = await driver.createCDPConnection('page');
await driver.logMutationEvents(cdpConnection, event => {
assert.deepStrictEqual(event['attribute_name'], 'style');
assert.deepStrictEqual(event['current_value'], "");
assert.deepStrictEqual(event['old_value'], "display:none;");
});
await driver.get('dynamic.html');
await driver.findElement({id: 'reveal'}).click();
let revealed = driver.findElement({id: 'revealed'});
await driver.wait(until.elementIsVisible(revealed), 5000);
await driver.quit();
}catch (e){
console.log(e)
}
}())
console.log
eventsListen to the console.log
events and register callbacks to process the event.
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
devTools.send(Log.enable());
devTools.addListener(Log.entryAdded(),
logEntry -> {
System.out.println("log: "+logEntry.getText());
System.out.println("level: "+logEntry.getLevel());
});
driver.get("http://the-internet.herokuapp.com/broken_images");
// Check the terminal output for the browser console messages.
driver.quit();
import trio
from selenium import webdriver
from selenium.webdriver.common.log import Log
async def printConsoleLogs():
chrome_options = webdriver.ChromeOptions()
driver = webdriver.Chrome()
driver.get("http://www.google.com")
async with driver.bidi_connection() as session:
log = Log(driver, session)
from selenium.webdriver.common.bidi.console import Console
async with log.add_listener(Console.ALL) as messages:
driver.execute_script("console.log('I love cheese')")
print(messages["message"])
driver.quit()
trio.run(printConsoleLogs)
using IJavaScriptEngine monitor = new JavaScriptEngine(driver);
List<string> consoleMessages = new List<string>();
monitor.JavaScriptConsoleApiCalled += (sender, e) =>
{
Console.WriteLine("Log: {0}", e.MessageContent);
};
await monitor.StartEventMonitoring();
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.get 'http://www.google.com'
logs = []
driver.on_log_event(:console) do |event|
logs.push(event)
puts logs.length
end
driver.execute_script('console.log("here")')
ensure
driver.quit
end
const {Builder} = require('selenium-webdriver');
(async () => {
try {
let driver = new Builder()
.forBrowser('chrome')
.build();
const cdpConnection = await driver.createCDPConnection('page');
await driver.onLogEvent(cdpConnection, function (event) {
console.log(event['args'][0]['value']);
});
await driver.executeScript('console.log("here")');
await driver.quit();
}catch (e){
console.log(e);
}
})()
fun kotlinConsoleLogExample() {
val driver = ChromeDriver()
val devTools = driver.devTools
devTools.createSession()
val logConsole = { c: ConsoleEvent -> print("Console log message is: " + c.messages)}
devTools.domains.events().addConsoleListener(logConsole)
driver.get("https://www.google.com")
val executor = driver as JavascriptExecutor
executor.executeScript("console.log('Hello World')")
val input = driver.findElement(By.name("q"))
input.sendKeys("Selenium 4")
input.sendKeys(Keys.RETURN)
driver.quit()
}
Listen to the JS Exceptions and register callbacks to process the exception details.
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
public void jsExceptionsExample() {
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
List<JavascriptException> jsExceptionsList = new ArrayList<>();
Consumer<JavascriptException> addEntry = jsExceptionsList::add;
devTools.getDomains().events().addJavascriptExceptionListener(addEntry);
driver.get("<your site url>");
WebElement link2click = driver.findElement(By.linkText("<your link text>"));
((JavascriptExecutor) driver).executeScript("arguments[0].setAttribute(arguments[1], arguments[2]);",
link2click, "onclick", "throw new Error('Hello, world!')");
link2click.click();
for (JavascriptException jsException : jsExceptionsList) {
System.out.println("JS exception message: " + jsException.getMessage());
System.out.println("JS exception system information: " + jsException.getSystemInformation());
jsException.printStackTrace();
}
}
async def catchJSException():
chrome_options = webdriver.ChromeOptions()
driver = webdriver.Chrome()
async with driver.bidi_connection() as session:
driver.get("<your site url>")
log = Log(driver, session)
async with log.add_js_error_listener() as messages:
# Operation on the website that throws an JS error
print(messages)
driver.quit()
List<string> exceptionMessages = new List<string>();
using IJavaScriptEngine monitor = new JavaScriptEngine(driver);
monitor.JavaScriptExceptionThrown += (sender, e) =>
{
exceptionMessages.Add(e.Message);
};
await monitor.StartEventMonitoring();
driver.Navigate.GoToUrl("<your site url>");
IWebElement link2click = driver.FindElement(By.LinkText("<your link text>"));
((IJavaScriptExecutor) driver).ExecuteScript("arguments[0].setAttribute(arguments[1], arguments[2]);",
link2click, "onclick", "throw new Error('Hello, world!')");
link2click.Click();
foreach (string message in exceptionMessages)
{
Console.WriteLine("JS exception message: {0}", message);
}
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.get '<your-site-url>'
exceptions = []
driver.on_log_event(:exception) do |event|
exceptions.push(event)
puts exceptions.length
end
#Actions causing JS exceptions
ensure
driver.quit
end
const {Builder, By} = require('selenium-webdriver');
(async () => {
try {
let driver = new Builder()
.forBrowser('chrome')
.build();
const cdpConnection = await driver.createCDPConnection('page')
await driver.onLogException(cdpConnection, function (event) {
console.log(event['exceptionDetails']);
})
await driver.get('https://the-internet.herokuapp.com');
const link = await driver.findElement(By.linkText('Checkboxes'));
await driver.executeScript("arguments[0].setAttribute(arguments[1], arguments[2]);", link, "onclick","throw new Error('Hello, world!')");
await link.click();
await driver.quit();
}catch (e){
console.log(e);
}
})()
fun kotlinJsErrorListener() {
val driver = ChromeDriver()
val devTools = driver.devTools
devTools.createSession()
val logJsError = { j: JavascriptException -> print("Javascript error: '" + j.localizedMessage + "'.") }
devTools.domains.events().addJavascriptExceptionListener(logJsError)
driver.get("https://www.google.com")
val link2click = driver.findElement(By.name("q"))
(driver as JavascriptExecutor).executeScript(
"arguments[0].setAttribute(arguments[1], arguments[2]);",
link2click, "onclick", "throw new Error('Hello, world!')"
)
link2click.click()
driver.quit()
}
If you want to capture network events coming into the browser and you want manipulate them you are able to do it with the following examples.
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.devtools.HasDevTools;
import org.openqa.selenium.devtools.NetworkInterceptor;
import org.openqa.selenium.remote.http.Contents;
import org.openqa.selenium.remote.http.Filter;
import org.openqa.selenium.remote.http.HttpResponse;
import org.openqa.selenium.remote.http.Route;
NetworkInterceptor interceptor = new NetworkInterceptor(
driver,
Route.matching(req -> true)
.to(() -> req -> new HttpResponse()
.setStatus(200)
.addHeader("Content-Type", MediaType.HTML_UTF_8.toString())
.setContent(utf8String("Creamy, delicious cheese!"))));
driver.get("https://example-sausages-site.com");
String source = driver.getPageSource();
assertThat(source).contains("delicious cheese!");
Currently unavailable in python due the inability to mix certain async and sync commands
var handler = new NetworkResponseHandler()
{
ResponseMatcher = httpresponse => true,
ResponseTransformer = http => new()
{
StatusCode = 200,
Body = "Creamy, delicious cheese!"
}
};
INetwork networkInterceptor = driver.Manage().Network;
networkInterceptor.AddResponseHandler(handler);
await networkInterceptor.StartMonitoring();
driver.Navigate().GoToUrl("https://www.selenium.dev");
await networkInterceptor.StopMonitoring();
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
driver.intercept do |request, &continue|
uri = URI(request.url)
if uri.path.end_with?('one.js')
uri.path = '/devtools_request_interception_test/two.js'
request.url = uri.to_s
end
continue.call(request)
end
driver.navigate.to url_for('devToolsRequestInterceptionTest.html')
driver.find_element(tag_name: 'button').click
expect(driver.find_element(id: 'result').text).to eq('two')
const connection = await driver.createCDPConnection('page')
let url = fileServer.whereIs("/cheese")
let httpResponse = new HttpResponse(url)
httpResponse.addHeaders("Content-Type", "UTF-8")
httpResponse.body = "sausages"
await driver.onIntercept(connection, httpResponse, async function () {
let body = await driver.getPageSource()
assert.strictEqual(body.includes("sausages"), true, `Body contains: ${body}`)
})
driver.get(url)
val driver = ChromeDriver()
val interceptor = new NetworkInterceptor(
driver,
Route.matching(req -> true)
.to(() -> req -> new HttpResponse()
.setStatus(200)
.addHeader("Content-Type", MediaType.HTML_UTF_8.toString())
.setContent(utf8String("Creamy, delicious cheese!"))))
driver.get(appServer.whereIs("/cheese"))
String source = driver.getPageSource()
var handler = new NetworkRequestHandler()
{
RequestMatcher = httprequest => true,
ResponseSupplier = http => new()
{
StatusCode = 200,
Body = "Creamy, delicious cheese!"
}
};
INetwork networkInterceptor = driver.Manage().Network;
networkInterceptor.AddRequestHandler(handler);
await networkInterceptor.StartMonitoring();
driver.Navigate().GoToUrl("https://www.selenium.dev");
await networkInterceptor.StopMonitoring();
The following list of APIs will be growing as the WebDriver BiDirectional Protocol grows and browser vendors implement the same. Additionally, Selenium will try to support real-world use cases that internally use a combination of W3C BiDi protocol APIs.
If there is additional functionality you’d like to see, please raise a feature request.
Page being translated from English to Chinese. Do you speak Chinese? Help us to translate it by sending us pull requests!
This section contains the APIs related to browsing context commands.
Creates a new browsing context in a new window.
BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.WINDOW);
Creates a new browsing context in a new tab.
BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.TAB);
Creates a browsing context for the existing tab/window to run commands.
String id = driver.getWindowHandle();
BrowsingContext browsingContext = new BrowsingContext(driver, id);
A reference browsing context is a top-level browsing context. The API allows to pass the reference browsing context, which is used to create a new window. The implementation is operating system specific.
BrowsingContext
browsingContext =
new BrowsingContext(driver, WindowType.WINDOW, driver.getWindowHandle());
A reference browsing context is a top-level browsing context. The API allows to pass the reference browsing context, which is used to create a new tab. The implementation is operating system specific.
BrowsingContext
browsingContext =
new BrowsingContext(driver, WindowType.TAB, driver.getWindowHandle());
BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.TAB);
NavigationResult info = browsingContext.navigate("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html");
BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.TAB);
NavigationResult info = browsingContext.navigate("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html",
ReadinessState.COMPLETE);
Provides a tree of all browsing contexts descending from the parent browsing context, including the parent browsing context.
String referenceContextId = driver.getWindowHandle();
BrowsingContext parentWindow = new BrowsingContext(driver, referenceContextId);
parentWindow.navigate("https://www.selenium.dev/selenium/web/iframes.html", ReadinessState.COMPLETE);
List<BrowsingContextInfo> contextInfoList = parentWindow.getTree();
Provides a tree of all browsing contexts descending from the parent browsing context, including the parent browsing context upto the depth value passed.
String referenceContextId = driver.getWindowHandle();
BrowsingContext parentWindow = new BrowsingContext(driver, referenceContextId);
parentWindow.navigate("https://www.selenium.dev/selenium/web/iframes.html", ReadinessState.COMPLETE);
BrowsingContext window1 = new BrowsingContext(driver, driver.getWindowHandle());
BrowsingContext window2 = new BrowsingContext(driver, WindowType.WINDOW);
List<BrowsingContextInfo> contextInfoList = window1.getTopLevelContexts();
BrowsingContext window1 = new BrowsingContext(driver, WindowType.WINDOW);
BrowsingContext window2 = new BrowsingContext(driver, WindowType.WINDOW);
window2.close();
Page being translated from English to Chinese. Do you speak Chinese? Help us to translate it by sending us pull requests!
This section contains the APIs related to logging.
console.log
eventsListen to the console.log
events and register callbacks to process the event.
try (LogInspector logInspector = new LogInspector(driver)) {
CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
logInspector.onConsoleEntry(future::complete);
driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html");
driver.findElement(By.id("consoleLog")).click();
ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
const inspector = await LogInspector(driver)
await inspector.onConsoleEntry(function (log) {
logEntry = log
})
await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html')
await driver.findElement({ id: 'consoleLog' }).click()
assert.equal(logEntry.text, 'Hello, world!')
assert.equal(logEntry.realm, null)
assert.equal(logEntry.type, 'console')
assert.equal(logEntry.level, 'info')
assert.equal(logEntry.method, 'log')
assert.equal(logEntry.stackTrace, null)
assert.equal(logEntry.args.length, 1)
Listen to the JS Exceptions and register callbacks to process the exception details.
try (LogInspector logInspector = new LogInspector(driver)) {
CompletableFuture<JavascriptLogEntry> future = new CompletableFuture<>();
logInspector.onJavaScriptException(future::complete);
driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html");
driver.findElement(By.id("jsException")).click();
JavascriptLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
const inspector = await LogInspector(driver)
await inspector.onJavascriptException(function (log) {
logEntry = log
})
await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html')
await driver.findElement({ id: 'jsException' }).click()
assert.equal(logEntry.text, 'Error: Not working')
assert.equal(logEntry.type, 'javascript')
assert.equal(logEntry.level, 'error')
Listen to all JS logs at all levels and register callbacks to process the log.
try (LogInspector logInspector = new LogInspector(driver)) {
CompletableFuture<JavascriptLogEntry> future = new CompletableFuture<>();
logInspector.onJavaScriptLog(future::complete);
driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html");
driver.findElement(By.id("jsException")).click();
JavascriptLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
Selenium的核心库试图提供底层以及普适的功能. 每种语言的支持类都为常见交互提供特定的包装器, 可用于简化某些行为.
Expected Conditions are used with Explicit Waits. Instead of defining the block of code to be executed with a lambda, an expected conditions method can be created to represent common things that get waited on. Some methods take locators as arguments, others take elements as arguments.
These methods can include conditions such as:
允许您在每次发送特定 Selenium 命令时执行自定义操作
在测试中, 您偶尔会需要验证某事物的颜色;问题是网络上的颜色定义不是个常量. 如果有一种简单的方法可以比较颜色的十六进制与RGB呈现, 或者颜色的RGBA与HSLA呈现, 岂不美哉?
不用担心有一个解决方案:Color 类!
首先, 您需要导入该类:
import org.openqa.selenium.support.Color;
from selenium.webdriver.support.color import Color
// This feature is not implemented - Help us by sending a pr to implement this feature
include Selenium::WebDriver::Support
// This feature is not implemented - Help us by sending a pr to implement this feature
import org.openqa.selenium.support.Color
您现在可以开始创建颜色对象. 每个颜色对象都需要使用您颜色的字符串定义来创建. 支持的颜色定义如下:
private final Color HEX_COLOUR = Color.fromString("#2F7ED8");
private final Color RGB_COLOUR = Color.fromString("rgb(255, 255, 255)");
private final Color RGB_COLOUR = Color.fromString("rgb(40%, 20%, 40%)");
private final Color RGBA_COLOUR = Color.fromString("rgba(255, 255, 255, 0.5)");
private final Color RGBA_COLOUR = Color.fromString("rgba(40%, 20%, 40%, 0.5)");
private final Color HSL_COLOUR = Color.fromString("hsl(100, 0%, 50%)");
private final Color HSLA_COLOUR = Color.fromString("hsla(100, 0%, 50%, 0.5)");
HEX_COLOUR = Color.from_string('#2F7ED8')
RGB_COLOUR = Color.from_string('rgb(255, 255, 255)')
RGB_COLOUR = Color.from_string('rgb(40%, 20%, 40%)')
RGBA_COLOUR = Color.from_string('rgba(255, 255, 255, 0.5)')
RGBA_COLOUR = Color.from_string('rgba(40%, 20%, 40%, 0.5)')
HSL_COLOUR = Color.from_string('hsl(100, 0%, 50%)')
HSLA_COLOUR = Color.from_string('hsla(100, 0%, 50%, 0.5)')
// This feature is not implemented - Help us by sending a pr to implement this feature
HEX_COLOUR = Color.from_string('#2F7ED8')
RGB_COLOUR = Color.from_string('rgb(255, 255, 255)')
RGB_COLOUR = Color.from_string('rgb(40%, 20%, 40%)')
RGBA_COLOUR = Color.from_string('rgba(255, 255, 255, 0.5)')
RGBA_COLOUR = Color.from_string('rgba(40%, 20%, 40%, 0.5)')
HSL_COLOUR = Color.from_string('hsl(100, 0%, 50%)')
HSLA_COLOUR = Color.from_string('hsla(100, 0%, 50%, 0.5)')
// This feature is not implemented - Help us by sending a pr to implement this feature
private val HEX_COLOUR = Color.fromString("#2F7ED8")
private val RGB_COLOUR = Color.fromString("rgb(255, 255, 255)")
private val RGB_COLOUR_PERCENT = Color.fromString("rgb(40%, 20%, 40%)")
private val RGBA_COLOUR = Color.fromString("rgba(255, 255, 255, 0.5)")
private val RGBA_COLOUR_PERCENT = Color.fromString("rgba(40%, 20%, 40%, 0.5)")
private val HSL_COLOUR = Color.fromString("hsl(100, 0%, 50%)")
private val HSLA_COLOUR = Color.fromString("hsla(100, 0%, 50%, 0.5)")
Color类还支持在以下网址中指定的所有基本颜色定义 http://www.w3.org/TR/css3-color/#html4.
private final Color BLACK = Color.fromString("black");
private final Color CHOCOLATE = Color.fromString("chocolate");
private final Color HOTPINK = Color.fromString("hotpink");
BLACK = Color.from_string('black')
CHOCOLATE = Color.from_string('chocolate')
HOTPINK = Color.from_string('hotpink')
// This feature is not implemented - Help us by sending a pr to implement this feature
BLACK = Color.from_string('black')
CHOCOLATE = Color.from_string('chocolate')
HOTPINK = Color.from_string('hotpink')
// This feature is not implemented - Help us by sending a pr to implement this feature
private val BLACK = Color.fromString("black")
private val CHOCOLATE = Color.fromString("chocolate")
private val HOTPINK = Color.fromString("hotpink")
如果元素上未设置颜色, 则有时浏览器会返回“透明”的颜色值. Color类也支持此功能:
private final Color TRANSPARENT = Color.fromString("transparent");
TRANSPARENT = Color.from_string('transparent')
// This feature is not implemented - Help us by sending a pr to implement this feature
TRANSPARENT = Color.from_string('transparent')
// This feature is not implemented - Help us by sending a pr to implement this feature
private val TRANSPARENT = Color.fromString("transparent")
现在, 您可以安全地查询元素以获取其颜色/背景色, 任何响应都将被正确解析并转换为有效的Color对象:
Color loginButtonColour = Color.fromString(driver.findElement(By.id("login")).getCssValue("color"));
Color loginButtonBackgroundColour = Color.fromString(driver.findElement(By.id("login")).getCssValue("background-color"));
login_button_colour = Color.from_string(driver.find_element(By.ID,'login').value_of_css_property('color'))
login_button_background_colour = Color.from_string(driver.find_element(By.ID,'login').value_of_css_property('background-color'))
// This feature is not implemented - Help us by sending a pr to implement this feature
login_button_colour = Color.from_string(driver.find_element(id: 'login').css_value('color'))
login_button_background_colour = Color.from_string(driver.find_element(id: 'login').css_value('background-color'))
// This feature is not implemented - Help us by sending a pr to implement this feature
val loginButtonColour = Color.fromString(driver.findElement(By.id("login")).getCssValue("color"))
val loginButtonBackgroundColour = Color.fromString(driver.findElement(By.id("login")).getCssValue("background-color"))
然后, 您可以直接比较颜色对象:
assert loginButtonBackgroundColour.equals(HOTPINK);
assert login_button_background_colour == HOTPINK
// This feature is not implemented - Help us by sending a pr to implement this feature
assert(login_button_background_colour == HOTPINK)
// This feature is not implemented - Help us by sending a pr to implement this feature
assert(loginButtonBackgroundColour.equals(HOTPINK))
或者, 您可以将颜色转换为以下格式之一并执行静态验证:
assert loginButtonBackgroundColour.asHex().equals("#ff69b4");
assert loginButtonBackgroundColour.asRgba().equals("rgba(255, 105, 180, 1)");
assert loginButtonBackgroundColour.asRgb().equals("rgb(255, 105, 180)");
assert login_button_background_colour.hex == '#ff69b4'
assert login_button_background_colour.rgba == 'rgba(255, 105, 180, 1)'
assert login_button_background_colour.rgb == 'rgb(255, 105, 180)'
// This feature is not implemented - Help us by sending a pr to implement this feature
assert(login_button_background_colour.hex == '#ff69b4')
assert(login_button_background_colour.rgba == 'rgba(255, 105, 180, 1)')
assert(login_button_background_colour.rgb == 'rgb(255, 105, 180)')
// This feature is not implemented - Help us by sending a pr to implement this feature
assert(loginButtonBackgroundColour.asHex().equals("#ff69b4"))
assert(loginButtonBackgroundColour.asRgba().equals("rgba(255, 105, 180, 1)"))
assert(loginButtonBackgroundColour.asRgb().equals("rgb(255, 105, 180)"))
颜色不再是问题.
此类仅在Java中可用
ThreadGuard检查是否仅从创建驱动程序的同一线程中调用了驱动程序.
线程问题 (尤其是在Parallel中运行测试时)
可能遇到神秘并且难以诊断错误.
使用此包装器可以防止此类错误,
并且在发生此类情况时会抛出异常.
以下的示例模拟一种线程冲突的情况:
public class DriverClash {
//thread main (id 1) created this driver
private WebDriver protectedDriver = ThreadGuard.protect(new ChromeDriver());
static {
System.setProperty("webdriver.chrome.driver", "<Set path to your Chromedriver>");
}
//Thread-1 (id 24) is calling the same driver causing the clash to happen
Runnable r1 = () -> {protectedDriver.get("https://selenium.dev");};
Thread thr1 = new Thread(r1);
void runThreads(){
thr1.start();
}
public static void main(String[] args) {
new DriverClash().runThreads();
}
}
结果如下所示:
Exception in thread "Thread-1" org.openqa.selenium.WebDriverException:
Thread safety error; this instance of WebDriver was constructed
on thread main (id 1)and is being accessed by thread Thread-1 (id 24)
This is not permitted and *will* cause undefined behaviour
正如示例所示:
protectedDriver
将在主线程中创建Runnable
启动一个新进程, 并使用一个新的 Thread
运行该进程Thread
都会发生冲突, 因为主线程的内存中没有 protectedDriver
ThreadGuard.protect
会抛出异常这不能代替并发运行时使用 ThreadLocal
管理驱动程序的需求.
Select对象现在将为您提供一系列命令,
用于允许您与 <select>
元素进行交互.
如果您使用的是 Java 或 .NET, 请确保您在代码中已正确加载所需的包. 您可以通过GitHub查看下面示例的完整代码.
请注意,此类仅适用于 HTML 元素 select
和 option
.
这个类将不适用于那些通过 div
或 li
并使用JavaScript遮罩层设计的下拉列表.
选择方法的行为可能会有所不同,
具体取决于正在使用的 <select>
元素的类型.
这是标准的下拉对象,其只能选定一个选项.
<select name="selectomatic">
<option selected="selected" id="non_multi_option" value="one">One</option>
<option value="two">Two</option>
<option value="four">Four</option>
<option value="still learning how to count, apparently">Still learning how to count, apparently</option>
</select>
此选择列表允许同时选定和取消选择多个选项.
这仅适用于具有 multiple
属性的 <select>
元素.
<select name="multi" id="multi" multiple="multiple">
<option selected="selected" value="eggs">Eggs</option>
<option value="ham">Ham</option>
<option selected="selected" value="sausages">Sausages</option>
<option value="onion gravy">Onion gravy</option>
</select>
首先定位一个 <select>
元素,
然后借助其初始化一个Select
对象.
请注意, 从 Selenium 4.5 开始,
您无法针对禁用的 <select>
元素构建 Select
对象.
WebElement selectElement = driver.findElement(By.name("selectomatic"));
Select select = new Select(selectElement);
select_element = driver.find_element(By.NAME, 'selectomatic')
select = Select(select_element)
var selectElement = driver.FindElement(By.Name("selectomatic"));
var select = new SelectElement(selectElement);
select_element = driver.find_element(name: 'selectomatic')
select = Selenium::WebDriver::Support::Select.new(select_element)
const selectElement = await driver.findElement(By.name('selectomatic'))
const select = new Select(selectElement)
val selectElement = driver.findElement(By.name("selectomatic"))
val select = Select(selectElement)
共有两种列表可以被获取:
获取 <select>
元素中所有选项列表:
List<WebElement> optionList = select.getOptions();
option_list = select.options
IList<IWebElement> optionList = select.Options;
option_list = select.options
const optionList = await select.getOptions()
val optionList = select.getOptions()
获取 <select>
元素中所选中的选项列表.
对于标准选择列表这将只是一个包含一个元素的列表,
对于复选列表则表示包含的零个或多个元素.
List<WebElement> selectedOptionList = select.getAllSelectedOptions();
selected_option_list = select.all_selected_options
IList<IWebElement> selectedOptionList = select.AllSelectedOptions;
selected_option_list = select.selected_options
const selectedOptionList = await select.getAllSelectedOptions()
val selectedOptionList = select.getAllSelectedOptions()
Select类提供了三种选择选项的方法. 请注意, 对于复选类型的选择列, 对于要选择的每个元素可以重复使用这些方法.
根据其可见文本选择选项
select.selectByVisibleText("Four");
select.select_by_visible_text('Four')
select.SelectByText("Four");
select.select_by(:text, 'Four')
await select.selectByVisibleText('Four')
select.selectByVisibleText("Four")
根据其值属性选择选项
select.selectByValue("two");
select.select_by_value('two')
select.SelectByValue("two");
select.select_by(:value, 'two')
await select.selectByValue('two')
select.selectByValue("two")
根据其在列表中的位置选择选项
select.selectByIndex(3);
select.select_by_index(3)
select.SelectByIndex(3);
select.select_by(:index, 3)
await select.selectByIndex(3)
select.selectByIndex(3)
具有 disabled
属性的选项可能无法被选择.
<select name="single_disabled">
<option id="sinlge_disabled_1" value="enabled">Enabled</option>
<option id="sinlge_disabled_2" value="disabled" disabled="disabled">Disabled</option>
</select>
Assertions.assertThrows(UnsupportedOperationException.class, () -> {
select.selectByValue("disabled");
});
with pytest.raises(NotImplementedError):
select.select_by_value('disabled')
Assert.ThrowsException<InvalidOperationException>(() => select.SelectByValue("disabled"));
expect {
select.select_by(:value, 'disabled')
}.to raise_exception(Selenium::WebDriver::Error::UnsupportedOperationError)
await assert.rejects(async () => {
await select.selectByValue("disabled")
}, {
name: 'UnsupportedOperationError',
Assertions.assertThrows(UnsupportedOperationException::class.java) {
select.selectByValue("disabled")
}
只有复选类型的选择列表才能取消选择选项. 您可以对要选择的每个元素重复使用这些方法.
select.deselectByValue("eggs");
select.deselect_by_value('eggs')
select.DeselectByValue("eggs");
select.deselect_by(:value, 'eggs')
await select.deselectByValue('eggs')
select.deselectByValue("eggs")
It is not always obvious the root cause of errors in Selenium.
The most common Selenium-related error is a result of poor synchronization. Read about Waiting Strategies. If you aren’t sure if it is a synchronization strategy you can try temporarily hard coding a large sleep where you see the issue, and you’ll know if adding an explicit wait can help.
Note that many errors that get reported to the project are actually caused by issues in the underlying drivers that Selenium sends the commands to. You can rule out a driver problem by executing the command in multiple browsers.
If you have questions about how to do things, check out the Support options for ways get assistance.
If you think you’ve found a problem with Selenium code, go ahead and file a Bug Report on GitHub.
某些时候难以获得正确的CSS以及XPath选择器。
您尝试使用的CSS或XPath选择器包含无效字符或无效查询。
通过验证器服务运行选择器:
或者使用浏览器扩展程序来获取已知的良好值:
在您尝试找到该元素的当前时刻无法定位元素。
当成功定位到元素时, WebDriver会为其设置一个引用ID作为标记, 如果由于上下文环境发生变化, 导致之前元素的位置发生了变化或者无法找到了, WebDriver并不会自动重新定位, 任何使用之前元素所做的操作将报错该异常。
以下情况可能发生此异常:
frame
/ iframe
。DOM已变更
当页面刷新或页面上的项目各处移动时, 页面上仍然有一个具有所需定位器的元素, 它只是不再被正在使用的元素对象访问, 并且必须重新定位该元素才能再次使用。
这往往通过以下两种方式之一完成:
每次使用时都要重新定位元素。
尽管有可能元素在定位和使用元素之间的微秒内,
发生变化的可能性很小。
缺点是这不是最有效的方法,
尤其是在 Remote Grid
上运行时。
用另一个存储定位器的对象包装 Web 元素,并缓存定位的 Selenium 元素。 对该包装对象执行操作时,您可以尝试使用之前找到的缓存对象, 如果它是发生了变化,则可以捕获异常, 使用存储的定位器重新定位元素,并重试该方法。 这样效率更高,但如果您使用的定位器在页面更改后引用了不同的元素(而不是您想要的元素),则可能会导致问题。
上下文已变更
元素对象是针对特定的上下文存储的,
因此如果您切换到不同的上下文,
比如不同的 Window
或不同的 frame
或 iframe
元素引用仍然有效,
但暂时无法访问。在这种情况下,
重新定位元素无济于事,因为它在当前上下文中不存在。
要解决此问题,您需要确保在使用该元素之前切换回正确的上下文。
页面已变更
这种情况发生在您不仅更改了上下文, 而且导航到另一个页面并破坏了元素所在的上下文。 您无法仅从当前上下文重新定位它, 也无法切换回元素有效的活动上下文。 如果这是您的错误原因, 您必须回到正确的位置并重新定位元素。
Historically, this is the most common error beginning Selenium users get when trying to run code for the first time:
Through WebDriver, Selenium supports all major browsers. In order to drive the requested browser, Selenium needs to send commands to it via an executable driver. This error means the necessary driver could not be found by any of the means Selenium attempts to use.
There are several ways to ensure Selenium gets the driver it needs.
As of Selenium 4.6, Selenium downloads the correct driver for you. You shouldn’t need to do anything. If you are using the latest version of Selenium and you are getting an error, please turn on logging and file a bug report with that information.
If you want to read more information about how Selenium manages driver downloads for you, you can read about the Selenium Manager.
PATH
environment variableThis option first requires manually downloading the driver.
This is a flexible option to change location of drivers without having to update your code, and will work on multiple machines without requiring that each machine put the drivers in the same place.
You can either place the drivers in a directory that is already listed in PATH
,
or you can place them in a directory and add it to PATH
.
To see what directories are already on PATH
, open a Terminal and execute:
echo $PATH
If the location to your driver is not already in a directory listed, you can add a new directory to PATH:
echo 'export PATH=$PATH:/path/to/driver' >> ~/.bash_profile
source ~/.bash_profile
You can test if it has been added correctly by checking the version of the driver:
chromedriver --version
To see what directories are already on PATH
, open a Terminal and execute:
echo $PATH
If the location to your driver is not already in a directory listed, you can add a new directory to PATH:
echo 'export PATH=$PATH:/path/to/driver' >> ~/.zshenv
source ~/.zshenv
You can test if it has been added correctly by checking the version of the driver:
chromedriver --version
To see what directories are already on PATH
, open a Command Prompt and execute:
echo %PATH%
If the location to your driver is not already in a directory listed, you can add a new directory to PATH:
setx PATH "%PATH%;C:\WebDriver\bin"
You can test if it has been added correctly by checking the version of the driver:
chromedriver.exe --version
If you cannot upgrade to the latest version of Selenium, you do not want Selenium to download drivers for you, and you can’t figure out the environment variables, you can specify the location of the driver in the Service object.
You first need to download the desired driver,
then create an instance of the applicable Service
class and
set the path.
Specifying the location in the code itself has the advantage of not needing to figure out Environment Variables on your system, but has the drawback of making the code less flexible.
Before Selenium managed drivers itself, other projects were created to do so for you.
If you can’t use Selenium Manager because you are using an older version of Selenium (please upgrade), or need an advanced feature not yet implemented by Selenium Manager, you might try one of these tools to keep your drivers automatically updated:
浏览器 | 支持的操作系统 | 维护者 | 下载 | 问题追溯 |
---|---|---|---|---|
Chromium/Chrome | Windows/macOS/Linux | 下载 | Issues | |
Firefox | Windows/macOS/Linux | Mozilla | 下载 | Issues |
Edge | Windows/macOS/Linux | Microsoft | 下载 | Issues |
Internet Explorer | Windows | Selenium Project | 下载 | Issues |
Safari | macOS High Sierra and newer | Apple | 内置 | Issues |
备注:Opera驱动不再适用于Selenium的最新功能,目前官方不支持。
Turning on logging is a valuable way to get extra information that might help you determine why you might be having a problem.
Java logs are typically created per class. You can work with the default logger to work with all loggers. To filter out specific classes, see Filtering
Get the root logger:
Logger logger = Logger.getLogger("");
Java Logging is not exactly straightforward, and if you are just looking for an easy way to look at the important Selenium logs, take a look at the Selenium Logger project
Python logs are typically created per module. You can match all submodules by referencing the top level module. So to work with all loggers in selenium module, you can do this:
logger = logging.getLogger('selenium')
.NET does not currently have a Logging implementation
If you want to see as much debugging as possible in all the classes,
you can turn on debugging globally in Ruby by setting $DEBUG = true
.
For more fine-tuned control, Ruby Selenium created its own Logger class to wrap the default Logger
class.
This implementation provides some interesting additional features.
Obtain the logger directly from the #logger
class method on the Selenium::WebDriver
module:
logger = Selenium::WebDriver.logger
const logging = require('selenium-webdriver/lib/logging')
logger = logging.getLogger('webdriver')
Logger level helps to filter out logs based on their severity.
Java has 7 logger levels: SEVERE
, WARNING
, INFO
, CONFIG
, FINE
, FINER
, and FINEST
.
The default is INFO
.
You have to change both the level of the logger and the level of the handlers on the root logger:
logger.setLevel(Level.FINE);
Arrays.stream(logger.getHandlers()).forEach(handler -> {
handler.setLevel(Level.FINE);
});
Python has 6 logger levels: CRITICAL
, ERROR
, WARNING
, INFO
, DEBUG
, and NOTSET
.
The default is WARNING
To change the level of the logger:
logger.setLevel(logging.DEBUG)
Things get complicated when you use PyTest, though. By default, PyTest hides logging unless the test fails. You need to set 3 things to get PyTest to display logs on passing tests.
To always output logs with PyTest you need to run with additional arguments.
First, -s
to prevent PyTest from capturing the console.
Second, -p no:logging
, which allows you to override the default PyTest logging settings so logs can
be displayed regardless of errors.
So you need to set these flags in your IDE, or run PyTest on command line like:
pytest -s -p no:logging
Finally, since you turned off logging in the arguments above, you now need to add configuration to turn it back on:
logging.basicConfig(level=logging.WARN)
.NET does not currently have a Logging implementation
Ruby logger has 5 logger levels: :debug
, :info
, :warn
, :error
, :fatal
.
As of Selenium v4.9.1, The default is :info
.
To change the level of the logger:
logger.level = :debug
JavaScript has 9 logger levels: OFF
, SEVERE
, WARNING
, INFO
, DEBUG
, FINE
, FINER
, FINEST
, ALL
.
The default is OFF
.
To change the level of the logger:
logger.setLevel(logging.Level.INFO)
Things are logged as warnings if they are something the user needs to take action on. This is often used for deprecations. For various reasons, Selenium project does not follow standard Semantic Versioning practices. Our policy is to mark things as deprecated for 3 releases and then remove them, so deprecations may be logged as warnings.
Java logs actionable content at logger level WARN
Example:
May 08, 2023 9:23:38 PM dev.selenium.troubleshooting.LoggingTest logging
WARNING: this is a warning
Python logs actionable content at logger level — WARNING
Details about deprecations are logged at this level.
Example:
WARNING selenium:test_logging.py:23 this is a warning
.NET does not currently have a Logging implementation
Ruby logs actionable content at logger level — :warn
.
Details about deprecations are logged at this level.
For example:
2023-05-08 20:53:13 WARN Selenium [:example_id] this is a warning
Because these items can get annoying, we’ve provided an easy way to turn them off, see filtering section below.
This is the default level where Selenium logs things that users should be aware of but do not need to take actions on. This might reference a new method or direct users to more information about something
Java logs useful information at logger level INFO
Example:
May 08, 2023 9:23:38 PM dev.selenium.troubleshooting.LoggingTest logging
INFO: this is useful information
Python logs useful information at logger level — INFO
Example:
INFO selenium:test_logging.py:22 this is useful information
.NET does not currently have a Logging implementation
Ruby logs useful information at logger level — :info
.
Example:
2023-05-08 20:53:13 INFO Selenium [:example_id] this is useful information
Logs useful information at level: INFO
The debug log level is used for information that may be needed for diagnosing issues and troubleshooting problems.
Java logs most debug content at logger level FINE
Example:
May 08, 2023 9:23:38 PM dev.selenium.troubleshooting.LoggingTest logging
FINE: this is detailed debug information
Python logs debugging details at logger level — DEBUG
Example:
DEBUG selenium:test_logging.py:24 this is detailed debug information
.NET does not currently have a Logging implementation
Ruby only provides one level for debugging, so all details are at logger level — :debug
.
Example:
2023-05-08 20:53:13 DEBUG Selenium [:example_id] this is detailed debug information
Logs debugging details at level: FINER
and FINEST
Logs can be displayed in the console or stored in a file. Different languages have different defaults.
By default all logs are sent to System.err
. To direct output to a file, you need to add a handler:
Handler handler = new FileHandler("selenium.xml");
logger.addHandler(handler);
By default all logs are sent to sys.stderr
. To direct output somewhere else, you need to add a
handler with either a StreamHandler
or a FileHandler
:
handler = logging.FileHandler(log_path)
logger.addHandler(handler)
.NET does not currently have a Logging implementation
By default, logs are sent to the console in stdout
.
To store the logs in a file:
logger.output = file_name
JavaScript does not currently support sending output to a file.
To send logs to console output:
logging.installConsoleHandler()
Java logging is managed on a per class level, so
instead of using the root logger (Logger.getLogger("")
), set the level you want to use on a per-class
basis:
Logger.getLogger(RemoteWebDriver.class.getName()).setLevel(Level.FINEST);
Logger.getLogger(SeleniumManager.class.getName()).setLevel(Level.SEVERE);
logging.getLogger('selenium.webdriver.remote').setLevel(logging.WARN)
logging.getLogger('selenium.webdriver.common').setLevel(logging.DEBUG)
.NET does not currently have a Logging implementation
Ruby’s logger allows you to opt in (“allow”) or opt out (“ignore”) of log messages based on their IDs.
Everything that Selenium logs includes an ID. You can also turn on or off all deprecation notices by
using :deprecations
.
These methods accept one or more symbols or an array of symbols:
logger.ignore(:jwp_caps, :logger_info)
or
logger.allow(%i[selenium_manager example_id])
Want to support the Selenium project? Learn more or view the full list of sponsors.