如何在Selenium Webdriver中处理AJAX调用

什么是 Ajax?

AJAX 代表 Asynchronous JavaScript & XML(异步 JavaScript 和 XML),它允许网页从服务器检索少量数据,而无需重新加载整个页面。

Ajax 是一种用于创建快速动态网页的技术。这项技术是异步的,并结合使用了 Javascript 和 XML。它将在不重新加载整个页面的情况下更新网页的部分内容。一些使用 AJAX 技术的著名应用程序有 Gmail、Google 地图、Facebook、Youtube 等。

Ajax 如何工作?

例如,当您点击提交按钮时,JavaScript 将向服务器发出请求,解释结果并更新当前屏幕,而无需重新加载网页。

How Ajax Works

  • Ajax 调用是由浏览器发起的一种异步请求,不会直接导致页面转换。这意味着,如果您发出 Ajax 请求,用户仍然可以在应用程序上工作,而请求正在等待响应。
  • AJAX 将 HTTP 请求从客户端发送到服务器,然后处理服务器的响应,而无需重新加载整个页面。因此,当您进行 AJAX 调用时,您不能完全确定服务器发送响应所需的时间

从测试人员的角度来看,如果您正在检查要显示的内容或元素,您需要等待直到收到响应。在 AJAX 调用期间,数据以 XML 格式存储并从服务器检索。

如何在 Selenium Webdriver 中处理 Ajax 调用

处理 Ajax 调用的最大挑战是了解网页的加载时间。 由于网页加载时间仅持续几分之一秒,因此测试人员很难通过自动化工具测试此类应用程序。为此,Selenium Webdriver 必须在此 Ajax 调用上使用等待方法。

因此,通过执行此等待命令,Selenium 将暂停当前测试用例的执行,并等待预期的或新值。当新值或字段出现时,Selenium Webdriver 将执行暂停的测试用例。

以下是 Selenium Webdriver 可以使用的等待方法

Thread.Sleep()

  • Thread.Sleep() 不是一个明智的选择,因为它会将当前线程暂停指定的时间。
  • 在 AJAX 中,您永远无法确定确切的等待时间。因此,如果元素未在等待时间内显示,您的测试将失败。此外,它会增加开销,因为调用 Thread.sleep(t) 会使当前线程从运行队列移动到等待队列。
  • 当时间“t”到达后,当前线程将从等待队列移动到就绪队列,然后需要一些时间才能被 CPU 选中并运行。

隐式等待()

  • 此方法告诉 webdriver 如果元素不能立即获得,则等待,但此等待将持续整个浏览器打开时间。因此,页面上任何元素的搜索都可能需要隐式等待设置的时间。

显式等待()

  • 显式等待用于冻结测试执行,直到满足特定条件或达到最大时间。

WebdriverWait

  • 它可以用于任何条件。这可以通过 WebDriverWait 结合 ExpectedCondition 实现。
  • 动态等待元素的最佳方法是每秒检查条件,一旦条件满足,就继续执行脚本中的下一个命令。

但是所有这些等待的问题是,您必须指定超时单位。如果元素仍未在时间内出现怎么办?因此还有一种等待叫做 Fluent Wait。

Fluent Wait

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

在 Selenium Webdriver 中处理 Ajax 调用的挑战

  • 使用“暂停”命令处理 Ajax 调用并非完全可靠。长时间的暂停会使测试变得不可接受地慢,并增加测试时间。相反,“waitforcondition”在测试 Ajax 应用程序时会更有帮助。
  • 评估与特定 Ajax 应用程序相关的风险很困难
  • 给予开发人员完全的自由来修改 Ajax 应用程序使得测试过程充满挑战
  • 创建自动化测试请求对于测试工具可能很困难,因为此类 AJAX 应用程序通常使用不同的编码或序列化技术来提交 POST 数据。

使用 Selenium Webdriver 处理 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();
	}
	
}

摘要

  • AJAX 允许网页从服务器检索少量数据,而无需重新加载整个页面。
  • 要测试 Ajax 应用程序,应采用不同的等待方法
    • ThreadSleep
    • 隐式等待
    • 显式等待
    • WebdriverWait
    • Fluent Wait
  • 创建自动化测试请求对于测试工具可能很困难,因为此类 AJAX 应用程序通常使用不同的编码或序列化技术来提交 POST 数据。