大家好,我是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 是支持 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() 方法。
package com.devtools;import org.openqa.selenium.chrome.ChromeDriver;import org.openqa.selenium.devtools.DevTools;import java.util.HashMap;import java.util.Map;public class SetDeviceMode { final static String PROJECT_PATH = System.getProperty("user.dir"); public static void main(String[] args){ System.setProperty("webdriver.chrome.driver", PROJECT_PATH + "/src/main/resources/chromedriver"); ChromeDriver driver; driver = new ChromeDriver(); DevTools devTools = driver.getDevTools(); devTools.createSession(); Map deviceMetrics = new HashMap() {{ 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" 主页,如下图所示。
借助像 Applitools Eyes 我们不仅可以使用这些新的解决方案 Selenium 命令可以从不同的角度快速测试,并在规模上保持任何不一致性。Eyes 足够智能,不会由不同的浏览器和视图引起 UI 变化报告中小且难以察觉的错误结果。
模拟地理位置在许多情况下,我们需要测试基于位置的特定功能,如折扣、基于位置的价格等。因此,我们可以使用Devtols 模拟位置的API。
@Test public void mockLocation(){ 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 (InterruptedException e) { e.printStackTrace(); } }
在第21行,我们通过调用 getDevTools() 方法获取 DevTools 对象。然后,我们调用 send() 方法来启用 Network,并再次调用 send() 传递内置命令的方法 Network.emulateNetworkConditions() 与我们希望与此命令一起发送的参数。
最后,我们使用模拟网络条件打开它 Google 首页。
捕获HTTP请求使用 DevTools,我们可以捕获由应用程序启动的应用程序 HTTP 请求、访问方法、数据、头部信息等。
让我们看看如何使用示例代码捕获 HTTP 请求、URI 以及请求方法。
package com.devtools;import org.openqa.selenium.chrome.ChromeDriver;import org.openqa.selenium.devtools.DevTools;import org.openqa.selenium.devtools.network.Network;import java.util.Optional;public class CaptureNetworkTraffic { private static ChromeDriver driver; private static DevTools chromeDevTools; final static String PROJECT_PATH = System.getProperty("user.dir"); public static void main(String[] args){ System.setProperty("webdriver.chrome.driver", PROJECT_PATH + "/src/main/resources/chromedriver"); driver = new ChromeDriver(); chromeDevTools = driver.getDevTools(); chromeDevTools.createSession(); chromeDevTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty())); chromeDevTools.addListener(Network.requestWillBeSent(), entry -> { System.out.println("Request URI : " + entry.getRequest().getUrl()+"\n" + " With method : "+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响应可用时,我们可以监控URLL、响应头、响应代码等。要获得响应文本,请使用Network.getresponsebody方法。
@Test public void validateResponse() { final RequestId[] requestIds = new RequestId[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("Response Body: \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 如下所示,脚本捕获控制台日志。
package com.devtools;import org.openqa.selenium.chrome.ChromeDriver;import org.openqa.selenium.devtools.DevTools;import org.openqa.selenium.devtools.log.Log;public class CaptureConsoleLogs { private static ChromeDriver driver; private static DevTools chromeDevTools; final static String PROJECT_PATH = System.getProperty("user.dir"); public static void main(String[] args){ System.setProperty("webdriver.chrome.driver", PROJECT_PATH + "/src/main/resources/chromedriver"); driver = new ChromeDriver(); 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-5d63b2-3822-4a01-8197-acd8a7.图灵"); }}
第19行使用我们的代码 DevTools::send() 启用控制台日志捕获。
然后,我们添加了一个监控器来捕获应用程序记录的所有控制台日志。我们使用应用程序捕获的每个日志 getText() 提取日志文本并使用该方法 getLevel() 提取日志级别的方法。
最后,打开应用程序,捕获应用程序发布的控制台错误日志。
捕获性能指标在当今快节奏的世界里,我们应该以如此快的速度迭代构建软件,我们也应该迭代检测性能瓶颈。性能差的网站和加载慢的页面会让客户不满意。
这些指标每次施工都能验证吗?是的,我们可以!
捕获性能指标 CDP 命令是 Performance.enable。文档中可以找到关于此命令的信息。
让我们看看如何在那里 Selenium 4 和 Chrome DevTools API 完成这个过程。
package com.devtools;import org.openqa.selenium.chrome.ChromeDriver;import org.openqa.selenium.devtools.DevTools;import org.openqa.selenium.devtools.performance.Performance;import org.openqa.selenium.devtools.performance.model.Metric;import java.util.Arrays;import java.util.List;import java.util.stream.Collectors;public class GetMetrics { final static String PROJECT_PATH = System.getProperty("user.dir"); public static void main(String[] args){ System.setProperty("webdriver.chrome.driver", PROJECT_PATH + "/src/main/resources/chromedriver"); ChromeDriver driver = new ChromeDriver(); DevTools devTools = 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 调用此命令的方法。
package com.devtools;import org.apache.commons.codec.binary.Base64;import org.openqa.selenium.By;import org.openqa.selenium.chrome.ChromeDriver;import org.openqa.selenium.devtools.DevTools;import org.openqa.selenium.devtools.network.Network;import org.openqa.selenium.devtools.network.model.Headers;import java.util.HashMap;import java.util.Map;import java.util.Optional;public class SetAuthHeader { private static final String USERNAME = "guest"; private static final String PASSWORD = "guest"; final static String PROJECT_PATH = System.getProperty("user.dir"); public static void main(String[] args){ System.setProperty("webdriver.chrome.driver", PROJECT_PATH + "/src/main/resources/chromedriver"); ChromeDriver driver = new ChromeDriver(); //Create DevTools session and enable Network DevTools chromeDevTools = driver.getDevTools(); chromeDevTools.createSession(); chromeDevTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty())); //Open website driver.get("https://jigsaw.w3.org/HTTP/"); //Send authorization header Map<String, Object> headers = new HashMap<>(); String basicAuth ="Basic " + new String(new Base64().encode(String.format("%s:%s", USERNAME, PASSWORD).getBytes())); headers.put("Authorization", basicAuth); chromeDevTools.send(Network.setExtraHTTPHeaders(new Headers(headers))); //Click authentication test - this normally invokes a browser popup if unauthenticated driver.findElement(By.linkText("Basic Authentication test")).click(); String loginSuccessMsg = driver.findElement(By.tagName("html")).getText(); if(loginSuccessMsg.contains("Your browser made it!")){ System.out.println("Login successful"); }else{ System.out.println("Login failed"); } driver.quit(); }}
我们先用 DevTools 对象创建会话并启用 Network。展示在第25-26行。
接下来,我们打开我们的网站,创建身份验证标头进行发送。
在第35行,我们将 setExtraHTTPHeaders 命令发送到 send()同时发送标头数据。这部分将验证我们的身份,并允许我们绕过浏览器弹出窗口。
为了测试此功能,我们点击了基本身份验证测试链接。如果您手动尝试此操作,您将看到浏览器弹出窗口要求您登录。但由于我们发送了身份验证标头,这个弹出窗口不会出现在我们的脚本中。
相反,我们会收到“你的浏览器登录成功了!”。
总结通过添加 CDP API,Selenium 它变得更强大了。现在,我们可以加强我们的测试和捕获 HTTP 网络流量,收集性能指标,处理身份验证,模拟地理位置、时区和设备模式。以及 Chrome DevTools 任何其他可能出现的功能!
参考:
- 官方网站Selenium:https://www.selenium.dev/
- Selenium文档:https://www.selenium.dev/documentation/en/
- Selenium教程:https://www.selenium.dev/documentation/en/getting_started/
- Selenium API文档:https://www.selenium.dev/selenium/docs/api/py/index.html