如何在 Selenium 中處理警報和彈出窗口
1. 概述
在本教程中,我們將探討如何在 Selenium 中處理警報和彈出視窗。警報和彈出視窗是可能中斷自動化腳本流程的常見元素,因此有效管理它們對於確保測試順利執行至關重要。
首先,我們需要了解警報和彈出視窗有多種形式,並且需要不同的處理技術。
簡單警報是需要確認的基本通知,通常透過「確定」按鈕( HTML 瀏覽器標準的一部分)進行確認。確認警報提示使用者接受或拒絕操作,而提示警報則請求使用者輸入。此外,彈出視窗可以顯示為單獨的瀏覽器視窗或模式對話框。
在本教程中,我們將檢查 Web 測試期間可能遇到的警報和彈出視窗的類型。我們將示範如何使用 Selenium 與每個元素進行交互,以確保我們的測試不間斷地進行。
2.設定和配置
為了處理警報和彈出窗口,我們首先需要使用兩個必需的依賴項設定環境: Selenium Java庫,它提供自動化瀏覽器的核心功能,以及WebDriverManager ,它對於透過自動下載和配置瀏覽器驅動程式來管理瀏覽器驅動程式至關重要。
首先,讓我們在專案的pom.xml檔案中包含所需的依賴項:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.23.1</version>
</dependency>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>5.8.0</version>
</dependency>
設定依賴項後,我們初始化ChromeDriver的新實例來自動化 Google Chrome,但可以輕鬆修改此配置以適應其他瀏覽器:
private WebDriver driver;
@BeforeEach
public void setup() {
driver = new ChromeDriver();
}
@AfterEach
public void tearDown() {
driver.quit();
}
3. 處理簡單警報
在本節中,我們將重點放在使用 Selenium 處理簡單警報所需的實際步驟。簡單警報是帶有文字和“確定”按鈕的基本警報視窗:
我們將導航到演示簡單警報的範例網頁,並編寫 JUnit 測試來觸發和管理警報。 Javascript 警報測試頁提供了各種類型警報的範例,包括我們旨在處理的簡單警報:
@Test
public void whenSimpleAlertIsTriggered_thenHandleIt() {
driver.get("https://testpages.herokuapp.com/styled/alerts/alert-test.html");
driver.findElement(By.id("alertexamples")).click();
Alert alert = driver.switchTo().alert();
String alertText = alert.getText();
alert.accept();
assertEquals("I am an alert box!", alertText);
}
在此測試中,我們初始化 WebDriver 並導航到測試頁面。點擊“顯示警報框”按鈕即可觸發簡單警報。一旦觸發警報,我們就使用 Selenium 的switchTo().alert()方法將控制項從主瀏覽器視窗切換到警報視窗。
一旦我們進入警報窗口,我們現在就可以使用警報介面提供的方法與其進行互動。對於簡單的警報框,我們透過使用alert.accept().除了接受或消除警報之外,我們還可以使用其他有用的方法(例如alert.getText()從警報視窗中提取文字:
String alertText = alert.getText();
以這種方式處理警報至關重要,因為如果不這樣做,自動化腳本將遇到異常。讓我們透過觸發警報、故意不處理警報並嘗試點擊另一個元素來測試此行為:
@Test
public void whenAlertIsNotHandled_thenThrowException() {
driver.get("https://testpages.herokuapp.com/styled/alerts/alert-test.html");
driver.findElement(By.id("alertexamples")).click();
assertThrows(UnhandledAlertException.class, () -> {
driver.findElement(By.xpath("/html/body/div/div[1]/div[2]/a[2]")).click();
});
}
測試案例的結果證實,如果在嘗試與頁面上的其他元素互動之前未處理警報,則會引發UnhandledAlertException 。
4.處理確認警報
確認警報與簡單警報略有不同。它們通常在使用者操作需要確認時出現,例如刪除記錄或提交敏感資訊。與僅顯示「確定」按鈕的簡單警報不同,確認警報提供兩種選擇:「確定」確認操作或「取消」關閉操作。
為了示範如何處理確認警報,我們將繼續使用Javascript 警報測試頁。我們的目標是觸發確認警報並透過接受和拒絕它來與之交互,然後驗證結果。
讓我們看看如何在 Selenium 中處理確認警報:
@Test
public void whenConfirmationAlertIsTriggered_thenHandleIt() {
driver.get("https://testpages.herokuapp.com/styled/alerts/alert-test.html");
driver.findElement(By.id("confirmexample")).click();
Alert alert = driver.switchTo().alert();
String alertText = alert.getText();
alert.accept();
assertEquals("true", driver.findElement(By.id("confirmreturn")).getText());
driver.findElement(By.id("confirmexample")).click();
alert = driver.switchTo().alert();
alert.dismiss();
assertEquals("false", driver.findElement(By.id("confirmreturn")).getText());
}
在此測試中,我們首先導航頁面並透過點擊「顯示確認框」按鈕觸發確認警報。使用switchTo().alert(),我們將控制項切換到警報上並擷取文字以進行驗證。然後使用accept()方法接受警報,我們檢查頁面上顯示的結果以確認操作已成功完成。
為了進一步示範確認警報的處理,測試再次觸發警報,但這次,我們使用dismiss()方法來取消操作。取消操作後,我們驗證對應的操作是否已正確中止。
5.處理提示警報
與簡單警報和確認警報相比,提示警報是一種更具互動性的瀏覽器警報形式。與僅向使用者顯示訊息的簡單警報和確認警報不同,提示警報會顯示訊息和文字輸入字段,使用者可以在其中輸入回應:
當網頁上的操作需要使用者輸入時,通常會出現提示警報。在 Selenium 中處理這些警報涉及將所需的輸入文字傳送到警報,然後透過接受輸入或消除警報來管理回應。
為了示範如何處理提示警報,我們將使用相同的測試頁面來觸發提示警報。我們的目標是觸發警報,透過提交輸入與其交互,並驗證是否處理了正確的輸入。
讓我們來看一個範例,展示如何在 Selenium 中處理提示警報:
@Test
public void whenPromptAlertIsTriggered_thenHandleIt() {
driver.get("https://testpages.herokuapp.com/styled/alerts/alert-test.html");
driver.findElement(By.id("promptexample")).click();
Alert alert = driver.switchTo().alert();
String inputText = "Selenium Test";
alert.sendKeys(inputText);
alert.accept();
assertEquals(inputText, driver.findElement(By.id("promptreturn")).getText());
}
此測試導航至測試頁面並觸發提示警報。處理提示警報時的關鍵步驟是將輸入文字傳送到警報。我們使用sendKeys()在提示視窗的輸入欄位中輸入文字。在本例中,我們傳送字串「Selenium Test」作為輸入。發送輸入後,我們使用accept()方法提交輸入並關閉警報。
最後,我們透過檢查處理警報後頁面上顯示的文字來驗證是否提交了正確的輸入。此步驟可協助我們確保應用程式正確處理測試腳本為提示警報提供的輸入。
6. Selenium 中其他處理警報的概念
除了我們之前介紹的方法之外,Selenium 中用於管理警報的另外兩個重要概念是WebDriverWait的alertIsPresent()和處理NoAlertPresentException.
6.1.將alertIsPresent()與WebDriverWait結合使用
alertIsPresent()條件是 Selenium 的ExpectedConditions類別的一部份。它與 WebDriver 的wait功能結合使用,以暫停腳本的執行,直到頁面上出現警報,然後再與其互動。它在警報出現不是立即或不可預測的情況下非常有用。
讓我們看看如何將alertIsPresent()與WebDriverWait:
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
alert.accept();
在此實作中,我們沒有立即切換到警報,而是使用WebDriverWait和ExpectedConditions.alertIsPresent()來暫停腳本,直到偵測到警報。這種方法確保我們的腳本僅在警報可用於互動時才繼續執行。
6.2.處理NoAlertPresentException
有時,警報可能不會在我們期望的時候出現,如果我們嘗試與不存在的警報進行交互,我們的測試將失敗並出現**NoAlertPresentException** .為了處理這種情況,我們可以使用try-catch區塊來捕獲異常,並在警報不存在時繼續執行替代邏輯:
@Test
public void whenNoAlertIsPresent_thenHandleGracefully() {
driver.get("https://testpages.herokuapp.com/styled/alerts/alert-test.html");
boolean noAlertExceptionThrown = false;
try {
Alert alert = driver.switchTo().alert();
alert.accept();
} catch (NoAlertPresentException e) {
noAlertExceptionThrown = true;
}
assertTrue(noAlertExceptionThrown, "NoAlertPresentException should be thrown");
assertTrue(driver.getTitle().contains("Alerts"), "Page title should contain 'Alerts'");
}
7.處理彈出窗口
在本節中,我們將探討如何在 Selenium 中處理彈出窗口,並討論與處理它們相關的一些挑戰。彈出視窗是許多網站的常見功能,一般可分為兩大類:瀏覽器層級彈出視窗和網站應用程式彈出視窗。每個類別在 Selenium 中都需要不同的方法,並且處理它們的策略根據它們的行為和實現而有所不同。
7.1.瀏覽器級彈出視窗
瀏覽器層級彈出視窗由瀏覽器本身生成,與網頁的 HTML 內容無關。這些彈出視窗通常包括系統對話框,例如基本驗證視窗。瀏覽器層級彈出視窗不是 DOM 的一部分,因此無法直接使用 Selenium 的標準findElement()方法進行互動。
瀏覽器級彈出視窗的常見範例包括:
- 基本驗證彈出視窗:要求使用者在存取頁面之前輸入使用者名稱和密碼
- 文件上傳/下載對話框:當要求使用者上傳或下載檔案時出現
- 列印對話方塊:列印網頁或元素時由瀏覽器觸發
在本教程中,我們將重點展示如何處理基本身份驗證彈出視窗。在授予網頁存取權限之前,基本驗證彈出視窗需要憑證(使用者名稱和密碼)。我們將使用演示頁面基本身份驗證來觸發和處理彈出視窗:
像這樣的瀏覽器級彈出視窗無法透過標準 Web 元素檢查技術存取。因此,我們無法使用sendKeys()方法輸入憑證。相反,我們需要在瀏覽器層級處理這些彈出視窗。我們的方法是透過將必要的憑證直接嵌入到 URL 中來完全繞過彈出視窗。
讓我們看看如何在 Selenium 中處理基本驗證彈出視窗:
@Test
public void whenBasicAuthPopupAppears_thenBypassWithCredentials() {
String username = "admin";
String password = "admin";
String url = "https://" + username + ":" + password + "@the-internet.herokuapp.com/basic_auth";
driver.get(url);
String bodyText = driver.findElement(By.tagName("body")).getText();
assertTrue(bodyText.contains("Congratulations! You must have the proper credentials."));
}
在此範例中,我們透過將使用者名稱和密碼嵌入到 URL 中來繞過基本驗證彈出視窗。該技術適用於基本的 HTTP 驗證彈出視窗。然後,我們導航到指定的 URL,瀏覽器將請求傳送到伺服器,並在 URL 中嵌入憑證。伺服器識別這些憑證並驗證請求,而不會觸發瀏覽器級彈出視窗。
7.2. Web 應用程式彈出視窗
Web 應用程式彈出視窗是直接嵌入網頁 HTML 中的元素,也是應用程式前端的一部分。這些彈出視窗是使用 JavaScript 或 CSS 建立的,可以包含模式對話方塊、橫幅或自訂警報等元素。與瀏覽器級彈出視窗不同,Web 應用程式彈出視窗可以使用標準 Selenium 命令進行交互,因為它們存在於 DOM 中。
Web 應用程式彈出視窗的一些常見範例包括:
- 模態對話框:覆蓋並阻止使用者與頁面其餘部分交互,直到關閉
- Javascript 彈出視窗:由使用者操作觸發,例如確認刪除或提交表單
- 自訂警報和 Toast:通知使用者有關操作的通知或訊息
在本教程中,我們將專注於處理許多 Web 應用程式的模式對話方塊。
模式對話方塊顯示重要資訊或提示使用者輸入,而無需離開頁面。在本節中,我們將重點介紹如何使用 Selenium 與模式對話框互動 - 特別是如何關閉它們:
通常,我們會檢查模式的 HTML 結構以查找關閉按鈕或其他互動元素。一旦確定,我們就可以使用 Selenium 的click()方法來關閉模式。
以下是如何使用標準 Selenium click()方法處理模式對話框的範例:
@Test
public void whenModalDialogAppears_thenCloseIt() {
driver.get("https://the-internet.herokuapp.com/entry_ad");
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10), Duration.ofMillis(500));
WebElement modal = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("modal")));
WebElement closeElement = driver.findElement(By.xpath("//div[@class='modal-footer']/p"));
closeElement.click();
WebDriverWait modalWait = new WebDriverWait(driver, Duration.ofSeconds(10));
boolean modalIsClosed = modalWait.until(ExpectedConditions.invisibilityOf(modal));
assertTrue(modalIsClosed, "The modal should be closed after clicking the close button");
}
在此測試中, WebDriverWait確保模式在與其互動之前完全可見。模式出現後,我們找到關閉按鈕(在本例中,是模式頁腳內的<p>元素)並呼叫click()方法將其關閉。
點擊後,我們使用ExpectedConditions.invisibilityOf.我們的測試通過了,表明模式已被發現並成功關閉。
八、結論
在本文中,我們學習如何使用switchTo().alert()進行 JavaScript 警報,使用accept() 、 dismiss()和sendKeys()方法,如何利用WebDriverWait和alertIsPresent()來實現更好的同步,以及如何繞過瀏覽器級身份驗證彈出視窗。
關鍵的一點是,我們需要記住,具體方法可能會根據應用程式的實作而有所不同,因此我們需要相應地調整我們的策略。本教學的完整原始碼可在 GitHub 上取得。