大家好,我是Yuan,今日为大家介绍Selenium自动化浏览器。就是这样!你能够经过这种力气做任何你想做的事情。

“getDevTools() 办法回来新的 Chrome DevTools 目标,答应您运用 send() 办法发送针对 CDP 的内置 Selenium 指令。这些指令是包装办法,使调用 CDP 函数愈加明晰和简便。”

——SHAMA UGALE

首要,什么是 Chrome DevTools?

Chrome DevTools 简介

Chrome DevTools 是一组直接内置在根据 Chromium 的浏览器(如 Chrome、Opera 和 Microsoft Edge)中的东西,用于帮助开发人员调试和研讨网站。

凭借 Chrome DevTools,开发人员能够更深入地拜访网站,并能够:

  • 检查 DOM 中的元素

  • 即时修改元素和 CSS

  • 检查和监控网站的功能

  • 模仿用户的地理方位

  • 模仿更快/更慢的网络速度

  • 履行和调试 JavaScript

  • 检查控制台日志

  • 等等

Selenium 4 Chrome DevTools API

Selenium 是支撑 web 浏览器自动化的一系列东西和库的综合项目。Selenium 4 增加了对 Chrome DevTools API 的原生支撑。凭借这些新的 API,咱们的测验现在能够:

  • 捕获和监控网络流量和功能

  • 模仿地理方位,用于方位感知测验、本地化和国际化测验

  • 更改设备形式并测验运用的呼应性

这只是冰山一角!

Selenium 4 引入了新的 ChromiumDriver 类,其间包括两个办法用于拜访 Chrome DevTools:getDevTools() 和 executeCdpCommand()。

getDevTools() 办法回来新的 DevTools 目标,答应您运用 send() 办法发送针对 CDP 的内置 Selenium 指令。这些指令是包装办法,使调用 CDP 函数愈加明晰和简便。

executeCdpCommand() 办法也答应您履行 CDP 办法,但愈加原始。它不运用包装的 API,而是答应您直接传入 Chrome DevTools 指令和该指令的参数。假如某个 CDP 指令没有 Selenium 包装 API,或许您期望以与 Selenium API 不同的方式进行调用,则能够运用 executeCdpCommand()。

像 ChromeDriver 和 EdgeDriver 这样的根据 Chromium 的驱动程序现在承继自 ChromiumDriver,因而您也能够从这些驱动程序中拜访 Selenium CDP API。

让咱们探索怎么利用这些新的 Selenium 4 API 来解决各种运用案例。

模仿设备形式

咱们今日构建的大多数运用都是呼应式的,以满足来自各种平台、设备(如手机、平板、可穿戴设备、桌面)和屏幕方向的终端用户的需求。

作为测验人员,咱们或许期望将咱们的运用程序放置在不同的尺寸中,以触发运用程序的呼应性。

咱们怎么运用 Selenium 的新 CDP 功能来实现这一点呢?

用于修改设备衡量的 CDP 指令是 Emulation.setDeviceMetricsOverride,并且此指令需要输入宽度、高度、移动设备标志和设备缩放因子。这四个键在此场景中是必需的,但还有一些可选的键。

在咱们的 Selenium 测验中,咱们能够运用 DevTools::send() 办法并运用内置的 setDeviceMetricsOverride() 指令,可是这个 Selenium API 接受 12 个参数 – 除了 4 个必需的参数外,还有 8 个可选的参数。关于咱们不需要发送的这 8 个可选参数中的任何一个,咱们能够传递 Optional.empty()。

然而,为了简化这个进程,只传递所需的参数,我将运用下面代码中的原始 executeCdpCommand() 办法。

packagecom.devtools;
importorg.openqa.selenium.chrome.ChromeDriver;
importorg.openqa.selenium.devtools.DevTools;
importjava.util.HashMap;
importjava.util.Map;
publicclassSetDeviceMode{
finalstaticStringPROJECT_PATH=System.getProperty("user.dir");
publicstaticvoidmain(String[]args){
System.setProperty("webdriver.chrome.driver",PROJECT_PATH+"/src/main/resources/chromedriver");
ChromeDriverdriver;
driver=newChromeDriver();
DevToolsdevTools=driver.getDevTools();
devTools.createSession();
MapdeviceMetrics=newHashMap()
{{
put("width",600);
put("height",1000);
put("mobile",true);
put("deviceScaleFactor",50);
}};
driver.executeCdpCommand("Emulation.setDeviceMetricsOverride",deviceMetrics);
driver.get("https://www.google.com");
}
}

在第19行,我创立了一个包含此指令所需键的映射。

然后在第26行,我调用 executeCdpCommand() 办法,并传递两个参数:指令名称为 “Emulation.setDeviceMetricsOverride”,以及包含参数的设备衡量映射。

在第27行,我翻开了渲染了我供给的规格的 “Google” 主页,如下图所示。

Selenium - 用这个力量做任何你想做的事情
凭借像 Applitools Eyes 这样的解决方案,咱们不仅能够运用这些新的 Selenium 指令在不同的视口上快速进行测验,还能够在规模上保持任何不一致性。Eyes 满足智能,不会对因为不同的浏览器和视口导致的 UI 中微小且难以发觉的变化报告过错的结果。

模仿地理方位

在许多情况下,咱们需要测验特定的根据方位的功能,例如优惠、根据方位的价格等。为此,咱们能够运用DevTools API来模仿方位。

@Test
publicvoidmockLocation(){
devTools.send(Emulation.setGeolocationOverride(
Optional.of(48.8584),
Optional.of(2.2945),
Optional.of(100)));
driver.get("https://mycurrentlocation.net/");
try{
Thread.sleep(30000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}

模仿网络速度

许多用户经过衔接到 Wi-Fi 或蜂窝网络的手持设备拜访 Web 运用程序。遇到信号弱的网络信号,因而互联网衔接速度较慢是很常见的。

在互联网衔接速度较慢(2G)或间歇性断网的情况下,测验运用程序在这种条件下的行为或许很重要。

假造网络衔接的 CDP 指令是 Network.emulateNetworkConditions。关于此指令的必需和可选参数的信息能够在文档中找到。

经过拜访 Chrome DevTools,就能够模仿这些场景。让咱们看看怎么做到这一点。

packagecom.devtools;
importorg.openqa.selenium.chrome.ChromeDriver;
importorg.openqa.selenium.devtools.DevTools;
importorg.openqa.selenium.devtools.network.Network;
importorg.openqa.selenium.devtools.network.model.ConnectionType;
importjava.util.HashMap;
importjava.util.Map;
importjava.util.Optional;
publicclassSetNetwork{
finalstaticStringPROJECT_PATH=System.getProperty("user.dir");
publicstaticvoidmain(String[]args){
System.setProperty("webdriver.chrome.driver",PROJECT_PATH+"/src/main/resources/chromedriver");
ChromeDriverdriver;
driver=newChromeDriver();

DevToolsdevTools=driver.getDevTools();
devTools.createSession();
devTools.send(Network.enable(Optional.empty(),Optional.empty(),Optional.empty()));
devTools.send(Network.emulateNetworkConditions(
false,
20,
20,
50,
Optional.of(ConnectionType.CELLULAR2G)
));
driver.get("https://www.google.com");
}
}

在第21行,咱们经过调用 getDevTools() 办法获取 DevTools 目标。然后,咱们调用 send() 办法来启用 Network,并再次调用 send() 办法来传递内置指令 Network.emulateNetworkConditions() 和咱们期望与此指令一起发送的参数。

最后,咱们运用模仿的网络条件翻开 Google 主页。

捕获HTTP恳求

运用 DevTools,咱们能够捕获运用程序发起的 HTTP 恳求,并拜访办法、数据、头信息等等。

让咱们看看怎么运用示例代码捕获 HTTP 恳求、URI 和恳求办法。

packagecom.devtools;
importorg.openqa.selenium.chrome.ChromeDriver;
importorg.openqa.selenium.devtools.DevTools;
importorg.openqa.selenium.devtools.network.Network;
importjava.util.Optional;
publicclassCaptureNetworkTraffic{
privatestaticChromeDriverdriver;
privatestaticDevToolschromeDevTools;
finalstaticStringPROJECT_PATH=System.getProperty("user.dir");
publicstaticvoidmain(String[]args){
System.setProperty("webdriver.chrome.driver",PROJECT_PATH+"/src/main/resources/chromedriver");
driver=newChromeDriver();
chromeDevTools=driver.getDevTools();
chromeDevTools.createSession();
chromeDevTools.send(Network.enable(Optional.empty(),Optional.empty(),Optional.empty()));
chromeDevTools.addListener(Network.requestWillBeSent(),
entry->{
System.out.println("RequestURI:"+entry.getRequest().getUrl()+"\n"
+"Withmethod:"+entry.getRequest().getMethod()+"\n");
entry.getRequest().getMethod();
});
driver.get("https://www.google.com");
chromeDevTools.send(Network.disable());
}
}

开始捕获网络流量的 CDP 指令是 Network.enable。关于此指令的必需和可选参数的信息能够在文档中找到。

在咱们的代码中,第22行运用 DevTools::send() 办法发送 Network.enable CDP 指令以启用网络流量捕获。

第23行增加了一个监听器,用于监听运用程序发送的一切恳求。关于运用程序捕获的每个恳求,咱们运用 getRequest().getUrl() 提取 URL,并运用 getRequest().getMethod() 提取 HTTP 办法。

第29行,咱们翻开了 Google 的主页,并在控制台上打印了此页面宣布的一切恳求的 URI 和 HTTP 办法。

一旦咱们完结了恳求的捕获,咱们能够发送 Network.disable 的 CDP 指令以中止捕获网络流量,如第30行所示。

阻拦HTTP呼应

为了阻拦呼应,咱们将运用Network.responseReceived事件。当HTTP呼应可用时触发此事件,咱们能够监听URL、呼应头、呼应代码等。要获取呼应正文,请运用Network.getResponseBody办法。

@Test
publicvoidvalidateResponse(){
finalRequestId[]requestIds=newRequestId[1];
devTools.send(Network.enable(Optional.of(100000000),Optional.empty(),Optional.empty()));
devTools.addListener(Network.responseReceived(),responseReceived->{
if(responseReceived.getResponse().getUrl().contains("api.zoomcar.com")){
System.out.println("URL:"+responseReceived.getResponse().getUrl());
System.out.println("Status:"+responseReceived.getResponse().getStatus());
System.out.println("Type:"+responseReceived.getType().toJson());
responseReceived.getResponse().getHeaders().toJson().forEach((k,v)->System.out.println((k+":"+v)));
requestIds[0]=responseReceived.getRequestId();
System.out.println("ResponseBody:\n"+devTools.send(Network.getResponseBody(requestIds[0])).getBody()+"\n");
}
});
driver.get("https://www.zoomcar.com/bangalore");
driver.findElement(By.className("search")).click();
}

拜访控制台日志

咱们都依靠日志来进行调试和剖析毛病。在测验和处理具有特定数据或特定条件的运用程序时,日志能够帮助咱们调试和捕获过错消息,供给更多在 Chrome DevTools 的控制台选项卡中发布的见地。

咱们能够经过调用 CDP 日志指令来经过咱们的 Selenium 脚本捕获控制台日志,如下所示。

packagecom.devtools;
importorg.openqa.selenium.chrome.ChromeDriver;
importorg.openqa.selenium.devtools.DevTools;
importorg.openqa.selenium.devtools.log.Log;
publicclassCaptureConsoleLogs{

privatestaticChromeDriverdriver;
privatestaticDevToolschromeDevTools;
finalstaticStringPROJECT_PATH=System.getProperty("user.dir");
publicstaticvoidmain(String[]args){
System.setProperty("webdriver.chrome.driver",PROJECT_PATH+"/src/main/resources/chromedriver");
driver=newChromeDriver();
chromeDevTools=driver.getDevTools();
chromeDevTools.createSession();
chromeDevTools.send(Log.enable());
chromeDevTools.addListener(Log.entryAdded(),
logEntry->{
System.out.println("log:"+logEntry.getText());
System.out.println("level:"+logEntry.getLevel());
});
driver.get("https://testersplayground.herokuapp.com/console-5d63b2b2-3822-4a01-8197-acd8aa7e1343.php");
}
}

在咱们的代码中,第19行运用 DevTools::send() 来启用控制台日志捕获。

然后,咱们增加一个监听器来捕获运用程序记录的一切控制台日志。关于运用程序捕获的每个日志,咱们运用 getText() 办法提取日志文本,并运用 getLevel() 办法提取日志等级。

最后,翻开运用程序并捕获运用程序发布的控制台过错日志。

捕获功能目标

在当今快节奏的国际中,咱们以如此快的速度迭代构建软件,咱们也应该迭代性地检测功能瓶颈。功能较差的网站和加载较慢的页面会让客户感到不满。

咱们能够在每次构建时验证这些目标吗?是的,咱们能够!

捕获功能目标的 CDP 指令是 Performance.enable。关于这个指令的信息能够在文档中找到。

让咱们看看怎么在 Selenium 4 和 Chrome DevTools API 中完结这个进程。

packagecom.devtools;
importorg.openqa.selenium.chrome.ChromeDriver;
importorg.openqa.selenium.devtools.DevTools;
importorg.openqa.selenium.devtools.performance.Performance;
importorg.openqa.selenium.devtools.performance.model.Metric;
importjava.util.Arrays;
importjava.util.List;
importjava.util.stream.Collectors;
publicclassGetMetrics{
finalstaticStringPROJECT_PATH=System.getProperty("user.dir");
publicstaticvoidmain(String[]args){
System.setProperty("webdriver.chrome.driver",PROJECT_PATH+"/src/main/resources/chromedriver");
ChromeDriverdriver=newChromeDriver();
DevToolsdevTools=driver.getDevTools();
devTools.createSession();
devTools.send(Performance.enable());
driver.get("https://www.google.org");
List<Metric>metrics=devTools.send(Performance.getMetrics());
List<String>metricNames=metrics.stream()
.map(o->o.getName())
.collect(Collectors.toList());
devTools.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:"+metrics.get(metricNames.indexOf(metric)).getValue()));
}
}

首要,咱们经过调用 DevTools 的 createSession() 办法创立一个会话,如第19行所示。

接下来,咱们经过将 Performance.enable() 指令发送给 send() 来启用 DevTools 来捕获功能目标,如第20行所示。

一旦启用了功能捕获,咱们能够翻开运用程序,然后将 Performance.getMetrics() 指令发送给 send()。这将回来一个 Metric 目标的列表,咱们能够经过流式处理来获取捕获的一切目标的名称,如第25行所示。

然后,咱们经过将 Performance.disable() 指令发送给 send() 来禁用功能捕获,如第29行所示。

为了检查咱们感兴趣的目标,咱们定义了一个名为 metricsToCheck 的列表,然后经过循环遍历该列表来打印目标的值。

根本身份验证

在 Selenium 中,无法与浏览器弹出窗口进行交互,因为它只能与 DOM 元素进行交互。这关于身份验证对话框等弹出窗口构成了挑战。

咱们能够经过运用 CDP API 直接与 DevTools 处理身份验证来绕过此问题。设置恳求的附加标头的 CDP 指令是 Network.setExtraHTTPHeaders。

以下是在 Selenium 4 中调用此指令的办法。

packagecom.devtools;
importorg.apache.commons.codec.binary.Base64;
importorg.openqa.selenium.By;
importorg.openqa.selenium.chrome.ChromeDriver;
importorg.openqa.selenium.devtools.DevTools;
importorg.openqa.selenium.devtools.network.Network;
importorg.openqa.selenium.devtools.network.model.Headers;
importjava.util.HashMap;
importjava.util.Map;
importjava.util.Optional;
publicclassSetAuthHeader{
privatestaticfinalStringUSERNAME="guest";
privatestaticfinalStringPASSWORD="guest";
finalstaticStringPROJECT_PATH=System.getProperty("user.dir");
publicstaticvoidmain(String[]args){
System.setProperty("webdriver.chrome.driver",PROJECT_PATH+"/src/main/resources/chromedriver");
ChromeDriverdriver=newChromeDriver();
//CreateDevToolssessionandenableNetwork
DevToolschromeDevTools=driver.getDevTools();
chromeDevTools.createSession();
chromeDevTools.send(Network.enable(Optional.empty(),Optional.empty(),Optional.empty()));
//Openwebsite
driver.get("https://jigsaw.w3.org/HTTP/");
//Sendauthorizationheader
Map<String,Object>headers=newHashMap<>();
StringbasicAuth="Basic"+newString(newBase64().encode(String.format("%s:%s",USERNAME,PASSWORD).getBytes()));
headers.put("Authorization",basicAuth);
chromeDevTools.send(Network.setExtraHTTPHeaders(newHeaders(headers)));
//Clickauthenticationtest-thisnormallyinvokesabrowserpopupifunauthenticated
driver.findElement(By.linkText("BasicAuthenticationtest")).click();
StringloginSuccessMsg=driver.findElement(By.tagName("html")).getText();
if(loginSuccessMsg.contains("Yourbrowsermadeit!")){
System.out.println("Loginsuccessful");
}else{
System.out.println("Loginfailed");
}
driver.quit();
}
}

咱们首要运用 DevTools 目标创立一个会话,并启用 Network。这在第25-26行中展示。

接下来,咱们翻开咱们的网站,然后创立用于发送的身份验证标头。

在第35行,咱们将 setExtraHTTPHeaders 指令发送到 send(),同时发送标头的数据。这部分将对咱们进行身份验证并答应咱们绕过浏览器弹出窗口。

为了测验这个功能,咱们点击了根本身份验证测验链接。假如您手动尝试这个操作,您会看到浏览器弹出窗口要求您进行登录。但因为咱们发送了身份验证标头,所以咱们的脚本中不会呈现这个弹出窗口。

相反,咱们会收到消息“您的浏览器登录成功!”。

总结

经过增加 CDP API,Selenium 已经变得愈加强大。现在,咱们能够增强咱们的测验,捕获 HTTP 网络流量,搜集功能目标,处理身份验证,并模仿地理方位、时区和设备形式。以及在 Chrome DevTools 中或许呈现的任何其他功能!

参阅:

  1. Selenium官方网站:www.selenium.dev/

  2. Selenium文档:www.selenium.dev/documentati…

  3. Selenium教程:www.selenium.dev/documentati…

  4. Selenium API文档:www.selenium.dev/selenium/do…

本文运用 文章同步助手 同步

转载:mp.weixin.qq.com/s/B5_76arsz…