Selenium 简明教程

Selenium WebDriver - Handling Ajax Calls

可以使用 Selenium Webdriver 处理 Ajax 调用。Ajax 又叫异步 JavaScript,主要由 * XML* 和 * JavaScript* 组成。从 UI 角度来看,对服务器发出 JavaScript 调用,然后我们从服务器接收 XML 格式的响应。

What is an Ajax?

  • Ajax* 或异步 JavaScript 主要用于创建快速响应的网页。我们以一个网页为例,其中用户的信息在单击按钮时更新。假设用户频繁更新其信息,因此每次都需要重新加载整个网页。但是,在基于 Ajax 构建的网页上,只需更新用户修改的部分用户信息,而不必重新加载整个页面。

Ajax 兼容于 HTTP 请求、JavaScript、XML、 * HTML* 、 * CSS* 等技术。Ajax 在不重新加载页面的情况下以异步方式指示和接收数据。

在 Ajax 系统中,用户界面向 XML HTTP 请求回调方法发送一个 JavaScript 调用,然后将一个 HTTP 请求指示给 Web 服务器。接下来,基于请求的 Web 服务器与数据库交换信息并以 JSON/XML 格式提取信息以反映在用户界面中。

How does Selenium Handle an Ajax Call?

Selenium Webdriver 在 Ajax 调用后并不总是成功访问 web 元素。这是因为在 Ajax Web 应用程序中,元素可用的等待时间并不统一。Selenium 测试在特定时间之后等待,之后我们会遇到故障。无法预测 Ajax 调用时间对 Selenium 测试来说是一个挑战。

为了克服这个问题,Selenium 使用了以下同步和等待机制 -

Thread.sleep()

此命令暂停执行一段时间,该时间以参数形式传递。然而,这不是一个好的选择,因为等待时间是固定的,但是无法预测 Ajax 调用时间。另外,此命令将当前线程从运行队列移到等待队列。

Implicit Wait

这是 Selenium 中提供的默认等待。它是一种全局等待,适用于整个驱动程序会话。默认等待时间为 0,这意味着如果没有找到元素,将立即抛出错误。但是,如果设置了等待时间,一旦等待时间超出了限制就会抛出错误。一旦识别出元素,就会返回其引用,并且执行将移至下一步。我们应该以最佳方式使用 implicit wait ,较长的等待时间会增加测试的执行时间。

Explicit Wait

这种类型的等待非常适合处理 Ajax 调用。一些预期显式等待的条件如下 -

  1. titleContains

  2. alertIsPresent

  3. invisibilityOfElementLocated

  4. titleIs

  5. invisibilityOfElementWithText

  6. visibilityOf

  7. textToBePresentInElement

  8. visibilityOfElementLocated

  9. visibilityOfAllElements

  10. presenceOfAllElementsLocatedBy

  11. presenceOfElementLocated

  12. elementToBeClickable

  13. stalenessOf

  14. textToBePresentInElementValue

  15. textToBePresentInElementLocated

  16. elementSelectionStateToBe

  17. elementToBeSelected

  18. frameToBeAvaliableAndSwitchToIt

Fluent Wait

这是 driver waits 的最大时间,用于判断元素满足特定条件的时间。它还确定驱动程序在找到元素或抛出异常之前进行验证(轮询间隔)的时间间隔。

Handling Ajax with Explicit Wait

让我们以以下页面的示例,我们会在其中单击 Click Me

selenium handling ajax calls 1

在单击 Click Me 时,我们将借助显式等待并等待文本 You have done a dynamic click 出现网页上。

selenium handling ajax calls 2

Example

package org.example;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
import java.util.concurrent.TimeUnit;

public class ExplicitsWait {
   public static void main(String[] args) throws InterruptedException {

      // Initiate the Webdriver
      WebDriver driver = new ChromeDriver();

      // adding implicit wait of 15 secs
      driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);

      // launching a browser
      driver.get("https://www.tutorialspoint.com/selenium/practice/buttons.php");

      // identify button then click on it
      WebElement l = driver.findElement
         (By.xpath("/html/body/main/div/div/div[2]/button[1]"));
      l.click();

      // Identify text
      WebElement e = driver.findElement(By.xpath("//*[@id='welcomeDiv']"));

      // explicit wait to expected condition for presence of a text
      WebDriverWait wt = new WebDriverWait(driver, Duration.ofSeconds(2));
      wt.until(ExpectedConditions.presenceOfElementLocated
         (By.xpath("//*[@id='welcomeDiv']")));

      // get text
      System.out.println("Get text after clicking: " + e.getText());

      // Quitting browser
      driver.quit();
   }
}
Get text after clicking: You have done a dynamic click

Process finished with exit code 0

在上例中,在单击 Click Me 按钮后出现的文本是 You have done a dynamic click

最后,收到了消息 Process finished with exit code 0 ,表示代码成功执行。

Handling Ajax with Fluent Wait

让我们以以下页面的另一个示例,我们在其中单击 Color Change

selenium handling ajax calls 3

在单击 Color Change 时,我们将借助流畅等待并等待按钮文本 Visible After 5 Seconds 出现在网页上。

selenium handling ajax calls 4

Example

package org.example;

import org.openqa.selenium.*;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import java.time.Duration;

public class Fluentwaits {
   public static void main(String[] args) throws InterruptedException {

      // Initiate the Webdriver
      WebDriver driver = new EdgeDriver();

      // launching a browser and open a URL
      driver.get("https://www.tutorialspoint.com/selenium/practice/dynamic-prop.php");

      // identify button then click
      WebElement l = driver.findElement(By.xpath("//*[@id='colorChange']"));
      l.click();

      // fluent wait of 6 secs till other button appears
      Wait<WebDriver> w = new FluentWait<WebDriver>(driver)
         .withTimeout(Duration.ofSeconds(20))     .pollingEvery(Duration.ofSeconds(6))
         .ignoring(NoSuchElementException.class);

      WebElement m = w.until
         (ExpectedConditions.visibilityOfElementLocated
         (By.xpath("//*[@id='visibleAfter']")));

      // checking button presence
      System.out.println("Button appeared: " + m.isDisplayed());

      // Quitting browser
      driver.quit();
   }
}
Button appeared: true

Handling Ajax with Implicit Wait

让我们以以下页面的示例,我们在其中尝试使用不正确的 xpath 值找到文本 Selenium Automation Practice Form 并使用隐式等待。期间,一旦超时时间过去,应该抛出 NoSuchElementException。

此元素的正确 xpath 应该是: /html/body/div/header/div[2]/h1 。但是,我们将在实现中使用错误的不正确 xpath - /html/body/div/header/div[2]/u1 以生成异常。

selenium handling ajax calls 5

Example

package org.example;

import org.openqa.selenium.*;
import org.openqa.selenium.edge.EdgeDriver;
import java.util.concurrent.TimeUnit;

public class Implicitwaits {
   public static void main(String[] args) throws InterruptedException {

      // Initiate the Webdriver
      WebDriver driver = new EdgeDriver();

      // adding implicit wait of 10 secs
      driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

      // launching a browser and open a URL
      driver.get("https://www.tutorialspoint.com/selenium/practice/selenium_automation_practice.php");

      // identify element with incorrect xpath value
      WebElement l = driver.findElement(By.xpath("/html/body/div/header/div[2]/u1"));
      l.click();

      // get text
      System.out.println("Get text : " + l.getText());

      // Quitting browser
      driver.quit();
   }
}
Exception in thread "main"
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element:
{"method":"xpath","selector":"/html/body/div/header/div[2]/u1"}
  (Session info: edge=121.0.6167.160)
For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception

Process finished with exit code 1

在上例中,由于使用了错误的 xpath 值来找到文本,因此我们获得了 NoSuchElementException。一旦 2 秒的隐式等待时间过去,我们就会得到一个异常。

最后,收到消息 Process finished with exit code 1 ,表示代码执行不成功。

Conclusion

这就结束了我们关于 Selenium Webdriver 处理 Ajax 调用的教程的全面介绍。我们从描述什么是 Ajax 开始,介绍 Selenium 如何处理 Ajax,并通过示例演示如何使用显式、隐式和流畅等待来处理 Ajax 及 Selenium。这使你深入了解了处理 Ajax 调用。明智的做法是不断实践你所学到的知识,并探索与 Selenium 相关的其他知识,以加深你的理解并拓展你的视野。