Selenium 简明教程
Selenium WebDriver - DevTools
Selenium Webdriver 的最新版本是 4.x 版本。Selenium 4 附带了许多改进,包括 Chrome DevTools(CDP) 上的新 API。它提供了对浏览器更精细的控制,可以对其执行测试。
What are the Chrome DevTools?
Chrome DevTools 是一系列针对基于 Chromium 的浏览器的工具,比如 Chrome、Edge 和 Opera。它们有助于启用调试,并获取关于测试中的应用程序的其他信息。CDP 的优势如下所示:
-
Obtain the Console Logs
-
Run and debug JavaScript
-
Mock Geolocations
-
在文档对象模型 (DOM) 中检查 Web 元素
-
Mock Network Traffic
-
Monitor Network Traffic
-
更新 Web 元素及其 CSS
Chrome DevTool APIs in Selenium 4
Selenium 4 可用于新的 Chrome 开发工具 API,这些 API 具有以下所列功能:
-
获取并监视网络流量。
-
模拟地理位置以进行本地化测试。
-
更新设备模式以检查 Web 应用程序的响应能力。
ChromiumDriver 类从 Selenium 4 版本引入。此类包含方法 getDevTools() 和 executeCdpCommand()。它们有助于访问 CDP。getDevTools() 方法会返回新的 DevTools 对象,它允许我们使用 send() 方法(CDP 的默认 Selenium 命令)。
这些命令主要是帮助调用 CDP 函数的封装方法。另一方面,executeCdpCommand() 方法可帮助在参数的帮助下运行 CDP 方法。它不依赖于任何封装 API。
ChromeDriver 和 EdgeDriver 类是从 ChromiumDriver 类继承的。因此,这些驱动程序也可以访问 Selenium CDP API。
Update Device Mode using CDP
让我们举一个示例,其中我们在其他设备中访问下面的应用程序。可以将应用程序配置为多种尺寸以验证其响应能力。为此使用的 CDP 命令是 Emulation.setDeviceMetricsOverride 命令。此命令中要传递的最小参数是 height、width、mobile 和 deviceScaleFactor。
作为替代方法,我们可以借助 setDeviceMetricsOverride() 方法来使用 DevTools::send() 方法。但是, setDeviceMetricsOverride() 使用 12 个参数。12 个参数中,4 个是必填,8 个是可选的。对于可选参数,我们必须使用 Optional.empty() 方法。
Example
package org.example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chromium.HasCdp;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.HasDevTools;
import org.openqa.selenium.edge.EdgeDriver;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class UpdateDeviceCDP {
public static void main(String[] args) throws InterruptedException {
//Initiate the Webdriver
WebDriver driver = new EdgeDriver();
//adding implicit wait of 15 secs
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
// instance of DevTools
DevTools d = ((HasDevTools) driver).getDevTools();
// create a session
d.createSession();
// device configurations
Map dM = new HashMap(){
{
put("width", 500);
put("height", 600);
put("mobile", true);
put("deviceScaleFactor", 50);
}
};
((HasCdp) driver).executeCdpCommand("Emulation.setDeviceMetricsOverride", dM);
// open application url
driver.get("https://www.tutorialspoint.com/selenium/practice/selenium_automation_practice.php");
}
}
它将显示以下输出 −
在上面的示例中,我们可以看到屏幕尺寸已经变小,具有在代码中传递的规格。
Simulate Network Speed using CDP
让我们举一个示例,其中当互联网连接为 2G 时,我们将检查应用程序的行为。CDP 命令 Network.emulateNetworkConditions 用于实现此目的。此命令中需要传递的至少 5 个参数是 offline、latency、download throughput、upload throughput 和 CONNECTIONTYPE。CONNECTIONTYPE 可以具有如下值:3G、2G、4G、BLUETOOTH、WIFI、ETHERNET 和 NONE。对于其他参数,我们必须使用 Optional.empty() 方法。
Example
package org.example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.HasDevTools;
import org.openqa.selenium.devtools.v124.network.model.ConnectionType;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.devtools.v124.network.Network;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
public class UpdateNetworkCDP {
public static void main(String[] args) throws InterruptedException {
//Initiate the Webdriver
WebDriver driver = new EdgeDriver();
//adding implicit wait of 15 secs
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
// instance of DevTools
DevTools d = ((HasDevTools) driver).getDevTools();
// create a session
d.createSession();
// network 2G configurations
d.send(Network.enable(Optional.empty(),Optional.empty(), Optional.empty()));
d.send(Network.emulateNetworkConditions(
false,
50,
30,
40,
Optional.of(ConnectionType.CELLULAR2G),
Optional.empty(),
Optional.empty(),
Optional.empty()
));
// open application url
driver.get("https://www.tutorialspoint.com/selenium/practice/selenium_automation_practice.php");
}
}
在上面的示例中,我们已经使用模拟的 2G 网络连接打开了应用程序。
Emulate Geolocations using CDP
让我们举一个示例,其中我们将使用 Emulation.setGeolocationOverride 命令来模拟地理位置。
Example
package org.example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.HasDevTools;
import org.openqa.selenium.devtools.v124.emulation.Emulation;
import org.openqa.selenium.edge.EdgeDriver;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
public class UpdateGeolocations {
public static void main(String[] args) throws InterruptedException {
//Initiate the Webdriver
WebDriver driver = new EdgeDriver();
//adding implicit wait of 15 secs
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
// instance of DevTools
DevTools d = ((HasDevTools) driver).getDevTools();
// create a session
d.createSession();
// update geolocations latitude and longitude
d.send(Emulation.setGeolocationOverride(
Optional.of(48.78232),
Optional.of(9.17702),
Optional.of(80)
));
// open application url
driver.get("https://where-am-i.org/");
}
}
它将显示以下输出 −
在上面的示例中,我们已将地理位置覆写为德国。
Obtain HTTP Requests using CDP
我们举一个示例,在该示例中,将在启动应用程序的同时获取 HTTP 请求及其响应、数据、标题等。要开始捕获网络流量,我们将设置与 send() 方法一起使用的 Network.enable 。此外,我们将分别使用 getRequest().getUrl() 和 getRequest().getMethod() 方法获取 URL 和方法名称。
Example
package org.example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.HasDevTools;
import org.openqa.selenium.devtools.v124.network.Network;
import org.openqa.selenium.edge.EdgeDriver;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
public class ObtainHttpReq {
public static void main(String[] args) throws InterruptedException {
//Initiate the Webdriver
WebDriver driver = new EdgeDriver();
//adding implicit wait of 15 secs
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
// instance of DevTools
DevTools d = ((HasDevTools) driver).getDevTools();
// create a session
d.createSession();
// get network traffic
d.send(Network.enable(Optional.empty(),
Optional.empty(), Optional.empty()));
d.addListener(Network.requestWillBeSent(),
e -> {
System.out.println("Get Request URI: " + e.getRequest().getUrl()+ "\n"
+ "along with method: "+ e.getRequest().getMethod() + "\n");
e.getRequest().getMethod();
});
// open application url
driver.get("https://www.tutorialspoint.com/selenium/practice/login.php");
// quit browser
driver.quit();
}
}
它将显示以下输出 −
Get Request URI:
https://www.tutorialspoint.com/selenium/practice/login.php
along with method: GET
Obtain Console Logs using CDP
我们举一个示例,在该示例中,将获取控制台日志。这有助于调试和对测试失败进行根本原因分析。要开始捕获控制台日志,我们将设置与 send() 方法一起使用的 Log.enable 。此外,我们将分别使用 getText() 和 getLevel() 方法获取日志文本和日志级别。
Example
package org.example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.HasDevTools;
import org.openqa.selenium.devtools.v124.log.Log;
import org.openqa.selenium.edge.EdgeDriver;
import java.util.concurrent.TimeUnit;
public class LogLevelCdp {
public static void main(String[] args) throws InterruptedException {
// Initiate the Webdriver
WebDriver driver = new EdgeDriver();
//adding implicit wait of 15 secs
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
// instance of DevTools
DevTools d = ((HasDevTools) driver).getDevTools();
// create a session
d.createSession();
// enable logging
d.send(Log.enable());
// get log levels and text
d.addListener(Log.entryAdded(),
logEntry -> {
System.out.println("Log text: "+logEntry.getText());
System.out.println("Log level: "+logEntry.getLevel());
});
// open application url
driver.get("https://www.tutorialspoint.com/selenium/practice/login.php");
// quit browser
driver.quit();
}
}
它将显示以下输出 −
Log text: [DOM] Input elements should have autocomplete attributes
(suggested: "current-password"):
(More info: https://www.chromium.org/developers/design-documents/create-amazing-password-forms) %o
Log level: verbose
Obtain Performance Metrics using CDP
我们举一个示例,在该示例中,将获取应用程序的性能指标。要开始捕获指标,我们将设置与 send() 方法一起使用的 Performance.enable 。此外,我们将使用 Performance.getMetrics() 方法获取所有指标。
Example 1
package org.example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.HasDevTools;
import org.openqa.selenium.devtools.v124.performance.Performance;
import org.openqa.selenium.devtools.v124.performance.model.Metric;
import org.openqa.selenium.edge.EdgeDriver;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
public class PerformanceMonitoringCdp {
public static void main(String[] args) throws InterruptedException {
//Initiate the Webdriver
WebDriver driver = new EdgeDriver();
//adding implicit wait of 15 secs
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
// instance of DevTools
DevTools d = ((HasDevTools) driver).getDevTools();
// create a session
d.createSession();
// enable performance monitoring
d.send(Performance.enable(Optional.empty()));
// open application url
driver.get("https://www.tutorialspoint.com/selenium/practice/text-box.php");
// get performance
List<Metric> m = d.send(Performance.getMetrics());
List<String> mN = m.stream()
.map(o -> o.getName())
.collect(Collectors.toList());
d.send(Performance.disable());
List<String> metricsToCheck = Arrays.asList(
"Timestamp", "Documents", "Frames", "JSEventListeners",
"LayoutObjects", "MediaKeySessions", "Nodes",
"Resources", "DomContentLoaded", "NavigationStart"
);
metricsToCheck.forEach( metric -> System.out.println(metric +
" is : " + m.get(mN.indexOf(metric)).getValue()));
// open application url
driver.get("https://www.tutorialspoint.com/selenium/practice/login.php");
// quit browser
driver.quit();
}
}
它将显示以下输出 −
Timestamp is : 15204.440213
Documents is : 7
Frames is : 4
JSEventListeners is : 30
LayoutObjects is : 170
MediaKeySessions is : 0
Nodes is : 528
Resources is : 10
DomContentLoaded is : 15204.419683
NavigationStart is : 15203.25931
Process finished with exit code 0
Example 2
我们举一个示例,在该示例中,将使用与 send() 方法一起使用的 CDP 命令 Network.setExtraHTTPHeaders 和标题数据执行基本身份验证。这将有助于验证身份并绕过任何弹出窗口。
让我们举下面的页面的示例,单击“基本身份验证”链接后,我们将获得一个弹出窗口,要求提供凭据。
凭据 admin 在“用户名”和“密码”字段中均已传递,然后单击 Sign In 按钮以继续。
最后,在成功身份验证后,我们将获得一个带有文本 - Congratulations! You must have the proper credentials 的页面。
代码实现
package org.example;
import com.google.common.collect.ImmutableMap;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.HasDevTools;
import org.openqa.selenium.devtools.v124.network.Network;
import org.openqa.selenium.devtools.v124.network.model.Headers;
import org.openqa.selenium.edge.EdgeDriver;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class BasicAuthCdp {
public static void main(String[] args) throws InterruptedException {
//Initiate the Webdriver
WebDriver driver = new EdgeDriver();
//adding implicit wait of 15 secs
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
// instance of DevTools
DevTools d = ((HasDevTools) driver).getDevTools();
// create a session
d.createSession();
d.send(Network.enable(Optional.empty(),Optional.empty(), Optional.empty()));
String encodedAuth = Base64.getEncoder().encodeToString("admin:admin".getBytes());
Map<String, Object> headers = ImmutableMap.of("Authorization", "Basic " + encodedAuth);
d.send(Network.setExtraHTTPHeaders(new Headers(headers)));
// open application
driver.get("https://the-internet.herokuapp.com/basic_auth");
WebElement e = driver.findElement(By.tagName("p"));
System.out.println("Text is: " + e.getText());
// quit browser
driver.quit();
}
}
它将显示以下输出 −
Text is: Congratulations! You must have the proper credentials.
Process finished with exit code 0
在上面的示例中,我们在标头中传递了身份验证,因此在触发测试时没有遇到弹出窗口。