大家好,我是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() 办法。

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 中渺小且难以觉察的变动报告谬误的后果。

模仿地理位置

在许多状况下,咱们须要测试特定的基于地位的性能,例如优惠、基于地位的价格等。为此,咱们能够应用DevTools 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();        }    }

模仿网络速度

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

在互联网连贯速度较慢(2G)或间歇性断网的状况下,测试应用程序在这种条件下的行为可能很重要。

伪造网络连接的 CDP 命令是 Network.emulateNetworkConditions。对于此命令的必须和可选参数的信息能够在文档中找到。

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

package com.devtools;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.ConnectionType;import java.util.HashMap;import java.util.Map;import java.util.Optional;public class SetNetwork {    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();        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 和申请办法。

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响应可用时触发此事件,咱们能够监听URL、响应头、响应代码等。要获取响应注释,请应用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-5d63b2b2-3822-4a01-8197-acd8aa7e1343.php");    }}

在咱们的代码中,第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 中可能呈现的任何其余性能!

参考:

  1. Selenium官方网站:https://www.selenium.dev/
  2. Selenium文档:https://www.selenium.dev/documentation/en/
  3. Selenium教程:https://www.selenium.dev/documentation/en/getting_started/
  4. Selenium API文档:https://www.selenium.dev/selenium/docs/api/py/index.html

本文由mdnice多平台公布