如何处理 AJAX 调用 Selenium 网络驱动程序

⚡ 智能摘要

AJAX 调用可以在不重新加载页面的情况下更新页面的一部分,因此 Selenium WebDriver 必须等待新内容出现,而不是假设它已经存在,等待策略决定了测试是否可靠地通过。

  • 🔘 定义: AJAX 异步获取少量数据,并且只刷新页面的一部分。
  • ☑️ 核心问题: 服务器响应时间未知,因此 WebDriver 查找时该元素可能不存在。
  • 等待选项: Thread.sleep、隐式等待、显式等待、WebDriverWait 和 FluentWait 的行为各不相同。
  • 🧪 推荐: WebDriverWait 带有 ExpectedCondition 会轮询直到 AJAX 结果出现,然后立即继续执行。
  • 🛠️ FluentWait: 它增加了一个轮询间隔,并且可以忽略两次尝试之间的特定异常情况。
  • ⚠️ Selenium 4: 超时现在需要持续时间,并且 Selenium 管理器移除手动驱动程序路径。

如何处理 AJAX 调用 Selenium 网络驱动程序

什么是 AJAX?

AJAX 代表异步 Java它使用脚本和 XML,允许网页从服务器检索少量数据,而无需重新加载整个页面。

AJAX 是一种用于构建快速、动态网页的技术。它是异步的,结合了…… JavaScript 采用数据格式,并更新页面的一部分而不是整个页面。 Gmail, Google 地图、Facebook 和 YouTube 大家都用它。

AJAX 的工作原理是什么?

例如,当你点击提交按钮时, Java脚本向服务器发送请求,解析结果,并在不刷新页面的情况下更新当前屏幕。下图展示了这一过程。

浏览器和服务器之间无需页面完全重新加载即可完成 AJAX 调用的示意图

  • AJAX 调用是浏览器发起的异步请求,不会导致页面跳转。用户可以在请求等待响应期间继续使用应用程序。
  • AJAX 向服务器发送 HTTP 请求并处理响应,而无需重新加载页面,因此您无法预测服务器需要多长时间才能响应。

从测试人员的角度来看,检查内容或元素意味着等待响应到达。顾名思义,最初的有效负载是 XML;现在大多数 API 返回的是 JSON。

如何处理 AJAX 调用 Selenium 网络驱动程序

处理 AJAX 调用的最大挑战在于掌握加载时间。由于更新过程仅持续不到一秒,因此很难通过自动化工具对应用程序进行测试。 Selenium WebDriver 必须对调用应用等待方法。

执行该等待命令会暂停当前操作。 测试用例 直到出现预期值或新值; Selenium WebDriver随后恢复了暂停的步骤。

以下是等待方法 Selenium WebDriver 可以使用

线程.sleep()

  • Thread.sleep() 不是一个明智的选择,因为它会暂停当前线程指定的时间。
  • 在 AJAX 中,你永远无法确定确切的等待时间,因此如果元素没有出现在等待队列中,测试就会失败。此外,它还会增加额外的开销,因为 `Thread.sleep(t)` 会将当前线程从运行队列移到等待队列。
  • 经过时间“t”后,线程移至就绪队列,然后再次等待被 CPU 调用。

注意: 这个 Java 方法是 线程.sleep() 请使用小写字母;大写形式无法编译。

隐式等待()

  • 此方法指示 WebDriver 在元素无法立即获取时等待,并且该设置在整个浏览器会话期间有效。因此,每次元素搜索都可以花费与隐式等待时间相同的时长。

显式等待()

  • 明确等待 用于冻结测试执行,直到满足特定条件或最大时间流逝为止。

网络驱动程序等待

  • 通过将 WebDriverWait 与 ExpectedCondition 结合使用,它可以用于任何情况。
  • 最佳方法是每秒检查一次条件,一旦满足条件就立即执行下一个命令。

但所有这些等待的问题是,你必须提到超时单位。如果元素在规定的时间内仍未出现怎么办?因此,还有一种等待称为 Fluent 等待。

流利的等待

  • 这是 Wait 接口的一个实现,它有自己的超时时间和轮询间隔。每个 FluentWait 实例都设置了等待某个条件的最大时间以及检查该条件的频率。

处理 AJAX 调用时面临的挑战 Selenium 网络驱动程序

  • 使用“暂停”命令并不可靠。长时间的暂停会导致测试速度过慢,难以接受,并且会增加误差。 测试与验证 由于时间关系,建议 AJAX 应用程序改用“waitforcondition”。
  • 评估特定 AJAX 应用程序相关的风险很困难。
  • 赋予开发者完全的修改 AJAX 应用程序的自由会使测试过程充满挑战。
  • 对于测试工具来说,创建自动化测试请求可能比较困难,因为 AJAX 应用程序通常使用不同的编码或序列化技术来提交 POST 数据。

注意: “暂停”和“等待条件”是 塞勒涅斯 命令已删除 Selenium 3;WebDriver 的等效方法是显式等待。

Code 使用 AJAX 处理的示例 Selenium 网络驱动程序

此 TestNG 下面的类读取文本,点击单选按钮,等待 AJAX 响应,并断言文本已更改。

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 org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

public class Ajaxdemo {
	
	private String URL = "https://demo.guru99.com/test/ajax.html";
	
	WebDriver driver;
	WebDriverWait wait;
	
	@BeforeClass
	public void setUp() {
		System.setProperty("webdriver.chrome.driver",".\\chromedriver.exe");
		//create chrome instance
		driver = new ChromeDriver();
		driver.manage().window().maximize();
		driver.navigate().to(URL);
	}
	
	@Test
	public void test_AjaxExample() {

		By container = By.cssSelector(".container");
		wait = new WebDriverWait(driver, 5);
		wait.until(ExpectedConditions.presenceOfElementLocated(container));
		
		//Get the text before performing an ajax call
		WebElement noTextElement = driver.findElement(By.className("radiobutton"));
		String textBefore = noTextElement.getText().trim();
		
		//Click on the radio button
		driver.findElement(By.id("yes")).click();
	
		//Click on Check Button
		driver.findElement(By.id("buttoncheck")).click();
		
		/*Get the text after ajax call*/
		WebElement TextElement = driver.findElement(By.className("radiobutton"));
		wait.until(ExpectedConditions.visibilityOf(TextElement));
		String textAfter = TextElement.getText().trim();
		
		/*Verify both texts before ajax call and after ajax call text.*/
		Assert.assertNotEquals(textBefore, textAfter);
		System.out.println("Ajax Call Performed");
		
		String expectedText = "Radio button is checked and it's value is Yes";
		
		/*Verify expected text with text updated after ajax call*/
		Assert.assertEquals(textAfter, expectedText);
		driver.close();
	}
	
}

注意: on Selenium 4通 持续时间.秒数(5) 改用 WebDriverWait 并删除 System.setProperty 这行代码,因为 Selenium 管理器解决 chromedriver 问题。

常见问题

不。int 和 long 构造函数已被移除。请改为传递 Duration.ofSeconds(5),并将 Duration 用于 implicitlyWait、pageLoadTimeout 和所有 FluentWait 设置。

使用 ExpectedConditions.invisibilityOfElementLocated 来配合微调定位器。单独等待目标元素出现往往为时过早,此时覆盖层仍然会阻挡点击操作。

在 wait until 代码块内执行脚本 return jQuery.active == 0。只有当没有 jQuery 请求处于打开状态时,它才会返回零。

AJAX 响应替换了 WebElement 指向的 DOM 节点。等待一段时间后,请重新定位该元素,而不是重用之前的引用。

AI 模型学习典型的响应时间,以调整每个元素的等待时间,标记间歇性故障而不是真正的故障,并将它们聚类,以便一次性修复一个根本原因。

是的。 GitHub 副驾驶 从评论中草拟 WebDriverWait 和 FluentWait 代码块,但确认 ExpectedCondition 与实际页面行为相符。

序号 Selenium 文档警告说,混合使用这两种方法会导致不可预测的超时。请将隐式等待时间设置为零,并仅使用显式等待。

从此以后 Selenium 4.6. Selenium 管理器下载并配置匹配的驱动程序,因此该行只需要固定本地驱动程序二进制文件即可。

总结一下这篇文章: