Selenium 简明教程

Selenium WebDriver - Handling Ajax Calls

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

Selenium Webdriver can be used to handle Ajax calls. Ajax also known as Asynchronous JavaScript is vastly made up of XML and JavaScript. From the UI point of view, a JavaScript call is made to the server and we receive the response in XML format from the server.

What is an Ajax?

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

Ajax or Asynchronous JavaScript is used mostly to create quick and responsive web pages. Let us take an example of a web page, where the user information updates on click of a button. Suppose a user is updating his information quite frequently, because of that, the whole web page needs to be reloaded each time. However, on a web page which is built on Ajax, only the part of user information which the user modified should be updated, rather than reloading the whole page.

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

Ajax is compliant with technologies like the HTTP request, JavaScript, XML, HTML, CSS, and so on. Ajax directs and receives data asynchronously without page reloading.

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

In an Ajax system, the user interface sends a JavaScript call to the XML HTTP request callback method, then a HTTP request is directed to the web server. Next, the web server on the basis of request exchanges information with the database, and fetches it in the JSON/XML format to reflect in the user interface.

How does Selenium Handle an Ajax Call?

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

Selenium Webdriver is not always successful in accessing the web elements post an Ajax call. This is because in an Ajax web application, the wait time for an element to be available is not uniform. Selenium tests wait for a specific amount of time after which we encounter failures. Inability to predict an Ajax call time is a challenge for the Selenium tests.

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

In order to overcome this, Selenium uses the the below synchronization and wait mechanisms −

Thread.sleep()

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

This command pauses the execution for the amount of time passed as a parameter. However, this is not a good choice, since the wait time is fixed, however, the Ajax call time cannot be predicted. Also, this command moves the current thread from the running queue to waiting.

Implicit Wait

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

It is the default wait available in Selenium. It is a kind of global wait applicable to the whole driver session. The default wait time is 0, meaning if an element is not found, an error will be thrown straight away. However, if a wait time is set, an error will be thrown once the wait time surpasses. Once the element is identified, its reference is returned and execution moves to the next step. We should use implicit wait in an optimal way, a larger wait time would increase the execution time of the tests.

Explicit Wait

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

This type of wait is ideal for handling the Ajax calls. Some of the expected conditions for explicit waits are listed below −

  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 的最大时间,用于判断元素满足特定条件的时间。它还确定驱动程序在找到元素或抛出异常之前进行验证(轮询间隔)的时间间隔。

This is the maximum time the driver waits for a specific condition for an element to be true. It also determines the interval at which the driver will verify(polling interval) prior to locating an element or throwing an exception.

Handling Ajax with Explicit Wait

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

Let us take an example of the below page, where we would click on Click Me.

selenium handling ajax calls 1

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

On clicking on Click Me, we would take the help of the explicit wait and hold back for the appearance of the text You have done a dynamic click on the web page.

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

In the above example, the text that appeared after clicking on the Click Me button was You have done a dynamic click.

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

Finally, the message Process finished with exit code 0 was received, signifying successful execution of the code.

Handling Ajax with Fluent Wait

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

Let us take another example of the below page where we would perform click on Color Change.

selenium handling ajax calls 3

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

On performing a click on Color Change, we would take the help of the fluent wait and hold back for the appearance of the button with the text Visible After 5 Seconds on the web page.

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。

Let us take an example of the below page, where we would make an attempt to locate the text Selenium Automation Practice Form with an incorrect xpath value and use an implicit wait. During that time, once the timeout time has passed, NoSuchElementException should be thrown.

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

The correct xpath for this element would be: /html/body/div/header/div[2]/h1. But, we would use erroneous an incorrect xpath - /html/body/div/header/div[2]/u1 in our implementation in order to generate an exception.

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 秒的隐式等待时间过去,我们就会得到一个异常。

In the above example, we had obtained the NoSuchElementException since an erroneous xpath value was used to locate the text. Once the implicit wait time of 2 seconds passed, we got an exception.

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

Finally, the message Process finished with exit code 1 is received, signifying unsuccessful execution of the code.

Conclusion

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

This concludes our comprehensive take on the tutorial on Selenium Webdriver Handling Ajax Calls. We’ve started with describing what an Ajax is, how Selenium handles Ajax, and walked through examples of how to use explicit, implicit, and fluent waits to handle Ajax along with Selenium. This equips you with in-depth knowledge of the handling Ajax Calls. It is wise to keep practicing what you’ve learned and exploring others relevant to Selenium to deepen your understanding and expand your horizons.