<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Selenium 自動(dòng)化 | 可以做任何你想做的事情!

          共 21502字,需瀏覽 44分鐘

           ·

          2023-08-02 20:18

          Chrome DevTools 簡(jiǎn)介

          Chrome DevTools 是一組直接內(nèi)置在基于 Chromium 的瀏覽器(如 Chrome、Opera 和 Microsoft Edge)中的工具,用于幫助開發(fā)人員調(diào)試和研究網(wǎng)站。

          借助 Chrome DevTools,開發(fā)人員可以更深入地訪問(wèn)網(wǎng)站,并能夠:

          • 檢查 DOM 中的元素
          • 即時(shí)編輯元素和 CSS
          • 檢查和監(jiān)控網(wǎng)站的性能
          • 模擬用戶的地理位置
          • 模擬更快/更慢的網(wǎng)絡(luò)速度
          • 執(zhí)行和調(diào)試 JavaScript
          • 查看控制臺(tái)日志
          • 等等

          Selenium 4 Chrome DevTools API

          9ca65c913c0a3c74762fa24353ba9219.webp

          Selenium 是支持 web 瀏覽器自動(dòng)化的一系列工具和庫(kù)的綜合項(xiàng)目。Selenium 4 添加了對(duì) Chrome DevTools API 的原生支持。借助這些新的 API,我們的測(cè)試現(xiàn)在可以:

          • 捕獲和監(jiān)控網(wǎng)絡(luò)流量和性能
          • 模擬地理位置,用于位置感知測(cè)試、本地化和國(guó)際化測(cè)試
          • 更改設(shè)備模式并測(cè)試應(yīng)用的響應(yīng)性

          這只是冰山一角!

          Selenium 4 引入了新的 ChromiumDriver 類,其中包括兩個(gè)方法用于訪問(wèn) Chrome DevTools:getDevTools() 和 executeCdpCommand()。

          getDevTools() 方法返回新的 DevTools 對(duì)象,允許您使用 send() 方法發(fā)送針對(duì) CDP 的內(nèi)置 Selenium 命令。這些命令是包裝方法,使調(diào)用 CDP 函數(shù)更加清晰和簡(jiǎn)便。

          executeCdpCommand() 方法也允許您執(zhí)行 CDP 方法,但更加原始。它不使用包裝的 API,而是允許您直接傳入 Chrome DevTools 命令和該命令的參數(shù)。如果某個(gè) CDP 命令沒(méi)有 Selenium 包裝 API,或者您希望以與 Selenium API 不同的方式進(jìn)行調(diào)用,則可以使用 executeCdpCommand()。

          像 ChromeDriver 和 EdgeDriver 這樣的基于 Chromium 的驅(qū)動(dòng)程序現(xiàn)在繼承自 ChromiumDriver,因此您也可以從這些驅(qū)動(dòng)程序中訪問(wèn) Selenium CDP API。

          讓我們探索如何利用這些新的 Selenium 4 API 來(lái)解決各種使用案例。

          模擬設(shè)備模式

          我們今天構(gòu)建的大多數(shù)應(yīng)用都是響應(yīng)式的,以滿足來(lái)自各種平臺(tái)、設(shè)備(如手機(jī)、平板、可穿戴設(shè)備、桌面)和屏幕方向的終端用戶的需求。

          作為測(cè)試人員,我們可能希望將我們的應(yīng)用程序放置在不同的尺寸中,以觸發(fā)應(yīng)用程序的響應(yīng)性。

          我們?nèi)绾问褂?Selenium 的新 CDP 功能來(lái)實(shí)現(xiàn)這一點(diǎn)呢?

          用于修改設(shè)備度量的 CDP 命令是 Emulation.setDeviceMetricsOverride,并且此命令需要輸入寬度、高度、移動(dòng)設(shè)備標(biāo)志和設(shè)備縮放因子。這四個(gè)鍵在此場(chǎng)景中是必需的,但還有一些可選的鍵。

          在我們的 Selenium 測(cè)試中,我們可以使用 DevTools::send() 方法并使用內(nèi)置的 setDeviceMetricsOverride() 命令,但是這個(gè) Selenium API 接受 12 個(gè)參數(shù) - 除了 4 個(gè)必需的參數(shù)外,還有 8 個(gè)可選的參數(shù)。對(duì)于我們不需要發(fā)送的這 8 個(gè)可選參數(shù)中的任何一個(gè),我們可以傳遞 Optional.empty()。

          然而,為了簡(jiǎn)化這個(gè)過(guò)程,只傳遞所需的參數(shù),我將使用下面代碼中的原始 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行,我創(chuàng)建了一個(gè)包含此命令所需鍵的映射。

          然后在第26行,我調(diào)用 executeCdpCommand() 方法,并傳遞兩個(gè)參數(shù):命令名稱為 "Emulation.setDeviceMetricsOverride",以及包含參數(shù)的設(shè)備度量映射。

          在第27行,我打開了渲染了我提供的規(guī)格的 "Google" 首頁(yè),如下圖所示。

          e8c945f40c4ba4d4f7140754a7172b05.webp

          借助像 Applitools Eyes 這樣的解決方案,我們不僅可以使用這些新的 Selenium 命令在不同的視口上快速進(jìn)行測(cè)試,還可以在規(guī)模上保持任何不一致性。Eyes 足夠智能,不會(huì)對(duì)由于不同的瀏覽器和視口導(dǎo)致的 UI 中微小且難以察覺的變化報(bào)告錯(cuò)誤的結(jié)果。

          模擬地理位置

          在許多情況下,我們需要測(cè)試特定的基于位置的功能,例如優(yōu)惠、基于位置的價(jià)格等。為此,我們可以使用DevTools API來(lái)模擬位置。

              
                @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();
                  }
              }

          模擬網(wǎng)絡(luò)速度

          許多用戶通過(guò)連接到 Wi-Fi 或蜂窩網(wǎng)絡(luò)的手持設(shè)備訪問(wèn) Web 應(yīng)用程序。遇到信號(hào)弱的網(wǎng)絡(luò)信號(hào),因此互聯(lián)網(wǎng)連接速度較慢是很常見的。

          在互聯(lián)網(wǎng)連接速度較慢(2G)或間歇性斷網(wǎng)的情況下,測(cè)試應(yīng)用程序在這種條件下的行為可能很重要。

          偽造網(wǎng)絡(luò)連接的 CDP 命令是 Network.emulateNetworkConditions。關(guān)于此命令的必需和可選參數(shù)的信息可以在文檔中找到。

          通過(guò)訪問(wèn) Chrome DevTools,就可以模擬這些場(chǎng)景。讓我們看看如何做到這一點(diǎn)。

              
              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行,我們通過(guò)調(diào)用 getDevTools() 方法獲取 DevTools 對(duì)象。然后,我們調(diào)用 send() 方法來(lái)啟用 Network,并再次調(diào)用 send() 方法來(lái)傳遞內(nèi)置命令 Network.emulateNetworkConditions() 和我們希望與此命令一起發(fā)送的參數(shù)。

          最后,我們使用模擬的網(wǎng)絡(luò)條件打開 Google 首頁(yè)。

          捕獲HTTP請(qǐng)求

          使用 DevTools,我們可以捕獲應(yīng)用程序發(fā)起的 HTTP 請(qǐng)求,并訪問(wèn)方法、數(shù)據(jù)、頭信息等等。

          讓我們看看如何使用示例代碼捕獲 HTTP 請(qǐng)求、URI 和請(qǐng)求方法。

              
              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());
              }
          }

          開始捕獲網(wǎng)絡(luò)流量的 CDP 命令是 Network.enable。關(guān)于此命令的必需和可選參數(shù)的信息可以在文檔中找到。

          在我們的代碼中,第22行使用 DevTools::send() 方法發(fā)送 Network.enable CDP 命令以啟用網(wǎng)絡(luò)流量捕獲。

          第23行添加了一個(gè)監(jiān)聽器,用于監(jiān)聽?wèi)?yīng)用程序發(fā)送的所有請(qǐng)求。對(duì)于應(yīng)用程序捕獲的每個(gè)請(qǐng)求,我們使用 getRequest().getUrl() 提取 URL,并使用 getRequest().getMethod() 提取 HTTP 方法。

          第29行,我們打開了 Google 的首頁(yè),并在控制臺(tái)上打印了此頁(yè)面發(fā)出的所有請(qǐng)求的 URI 和 HTTP 方法。

          一旦我們完成了請(qǐng)求的捕獲,我們可以發(fā)送 Network.disable 的 CDP 命令以停止捕獲網(wǎng)絡(luò)流量,如第30行所示。

          攔截HTTP響應(yīng)

          為了攔截響應(yīng),我們將使用Network.responseReceived事件。當(dāng)HTTP響應(yīng)可用時(shí)觸發(fā)此事件,我們可以監(jiān)聽URL、響應(yīng)頭、響應(yīng)代碼等。要獲取響應(yīng)正文,請(qǐng)使用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();
              }

          訪問(wèn)控制臺(tái)日志

          我們都依賴日志來(lái)進(jìn)行調(diào)試和分析故障。在測(cè)試和處理具有特定數(shù)據(jù)或特定條件的應(yīng)用程序時(shí),日志可以幫助我們調(diào)試和捕獲錯(cuò)誤消息,提供更多在 Chrome DevTools 的控制臺(tái)選項(xiàng)卡中發(fā)布的見解。

          我們可以通過(guò)調(diào)用 CDP 日志命令來(lái)通過(guò)我們的 Selenium 腳本捕獲控制臺(tái)日志,如下所示。

              
              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() 來(lái)啟用控制臺(tái)日志捕獲。

          然后,我們添加一個(gè)監(jiān)聽器來(lái)捕獲應(yīng)用程序記錄的所有控制臺(tái)日志。對(duì)于應(yīng)用程序捕獲的每個(gè)日志,我們使用 getText() 方法提取日志文本,并使用 getLevel() 方法提取日志級(jí)別。

          最后,打開應(yīng)用程序并捕獲應(yīng)用程序發(fā)布的控制臺(tái)錯(cuò)誤日志。

          捕獲性能指標(biāo)

          在當(dāng)今快節(jié)奏的世界中,我們以如此快的速度迭代構(gòu)建軟件,我們也應(yīng)該迭代性地檢測(cè)性能瓶頸。性能較差的網(wǎng)站和加載較慢的頁(yè)面會(huì)讓客戶感到不滿。

          我們能夠在每次構(gòu)建時(shí)驗(yàn)證這些指標(biāo)嗎?是的,我們可以!

          捕獲性能指標(biāo)的 CDP 命令是 Performance.enable。關(guān)于這個(gè)命令的信息可以在文檔中找到。

          讓我們看看如何在 Selenium 4 和 Chrome DevTools API 中完成這個(gè)過(guò)程。

              
              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()));
              }
          }

          首先,我們通過(guò)調(diào)用 DevTools 的 createSession() 方法創(chuàng)建一個(gè)會(huì)話,如第19行所示。

          接下來(lái),我們通過(guò)將 Performance.enable() 命令發(fā)送給 send() 來(lái)啟用 DevTools 來(lái)捕獲性能指標(biāo),如第20行所示。

          一旦啟用了性能捕獲,我們可以打開應(yīng)用程序,然后將 Performance.getMetrics() 命令發(fā)送給 send()。這將返回一個(gè) Metric 對(duì)象的列表,我們可以通過(guò)流式處理來(lái)獲取捕獲的所有指標(biāo)的名稱,如第25行所示。

          然后,我們通過(guò)將 Performance.disable() 命令發(fā)送給 send() 來(lái)禁用性能捕獲,如第29行所示。

          為了查看我們感興趣的指標(biāo),我們定義了一個(gè)名為 metricsToCheck 的列表,然后通過(guò)循環(huán)遍歷該列表來(lái)打印指標(biāo)的值。

          基本身份驗(yàn)證

          在 Selenium 中,無(wú)法與瀏覽器彈出窗口進(jìn)行交互,因?yàn)樗荒芘c DOM 元素進(jìn)行交互。這對(duì)于身份驗(yàn)證對(duì)話框等彈出窗口構(gòu)成了挑戰(zhàn)。

          我們可以通過(guò)使用 CDP API 直接與 DevTools 處理身份驗(yàn)證來(lái)繞過(guò)此問(wèn)題。設(shè)置請(qǐng)求的附加標(biāo)頭的 CDP 命令是 Network.setExtraHTTPHeaders。

          以下是在 Selenium 4 中調(diào)用此命令的方法。

              
              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 對(duì)象創(chuàng)建一個(gè)會(huì)話,并啟用 Network。這在第25-26行中展示。

          接下來(lái),我們打開我們的網(wǎng)站,然后創(chuàng)建用于發(fā)送的身份驗(yàn)證標(biāo)頭。

          在第35行,我們將 setExtraHTTPHeaders 命令發(fā)送到 send(),同時(shí)發(fā)送標(biāo)頭的數(shù)據(jù)。這部分將對(duì)我們進(jìn)行身份驗(yàn)證并允許我們繞過(guò)瀏覽器彈出窗口。

          為了測(cè)試這個(gè)功能,我們點(diǎn)擊了基本身份驗(yàn)證測(cè)試鏈接。如果您手動(dòng)嘗試這個(gè)操作,您會(huì)看到瀏覽器彈出窗口要求您進(jìn)行登錄。但由于我們發(fā)送了身份驗(yàn)證標(biāo)頭,所以我們的腳本中不會(huì)出現(xiàn)這個(gè)彈出窗口。

          相反,我們會(huì)收到消息“您的瀏覽器登錄成功!”。

          總結(jié)

          通過(guò)添加 CDP API,Selenium 已經(jīng)變得更加強(qiáng)大。現(xiàn)在,我們可以增強(qiáng)我們的測(cè)試,捕獲 HTTP 網(wǎng)絡(luò)流量,收集性能指標(biāo),處理身份驗(yàn)證,并模擬地理位置、時(shí)區(qū)和設(shè)備模式。以及在 Chrome DevTools 中可能出現(xiàn)的任何其他功能!

          鏈接: https://zhuanlan.zhihu.com/p/639947455

          瀏覽 54
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  五月婷婷六月天 | 少妇做受 高潮10在线 | 亚洲最黄日PP免费视频观看 | 久久99精品久久久久久水蜜桃 | 国产免费高清AV影视 |