Selenium 简明教程
Selenium WebDriver - Handling Ajax Calls
可以使用 Selenium Webdriver 处理 Ajax 调用。Ajax 又叫异步 JavaScript,主要由 * XML* 和 * JavaScript* 组成。从 UI 角度来看,对服务器发出 JavaScript 调用,然后我们从服务器接收 XML 格式的响应。
What is an Ajax?
-
Ajax* 或异步 JavaScript 主要用于创建快速响应的网页。我们以一个网页为例,其中用户的信息在单击按钮时更新。假设用户频繁更新其信息,因此每次都需要重新加载整个网页。但是,在基于 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 调用。一些预期显式等待的条件如下 -
-
titleContains
-
alertIsPresent
-
invisibilityOfElementLocated
-
titleIs
-
invisibilityOfElementWithText
-
visibilityOf
-
textToBePresentInElement
-
visibilityOfElementLocated
-
visibilityOfAllElements
-
presenceOfAllElementsLocatedBy
-
presenceOfElementLocated
-
elementToBeClickable
-
stalenessOf
-
textToBePresentInElementValue
-
textToBePresentInElementLocated
-
elementSelectionStateToBe
-
elementToBeSelected
-
frameToBeAvaliableAndSwitchToIt
Fluent Wait
这是 driver waits 的最大时间,用于判断元素满足特定条件的时间。它还确定驱动程序在找到元素或抛出异常之前进行验证(轮询间隔)的时间间隔。
Handling Ajax with Explicit Wait
让我们以以下页面的示例,我们会在其中单击 Click Me 。
在单击 Click Me 时,我们将借助显式等待并等待文本 You have done a dynamic click 出现网页上。
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 。
在单击 Color Change 时,我们将借助流畅等待并等待按钮文本 Visible After 5 Seconds 出现在网页上。
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 以生成异常。
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 ,表示代码执行不成功。