วิธีจัดการกับการโทรเข้า AJAX Selenium ไดรเวอร์เว็บ

⚡ สรุปอย่างชาญฉลาด

การเรียกใช้ AJAX จะอัปเดตส่วนหนึ่งของหน้าเว็บโดยไม่ต้องโหลดหน้าเว็บใหม่ ดังนั้น Selenium WebDriver ต้องรอเนื้อหาใหม่แทนที่จะสันนิษฐานว่ามีอยู่แล้ว และกลยุทธ์การรอจะเป็นตัวตัดสินว่าการทดสอบจะผ่านอย่างน่าเชื่อถือหรือไม่

  • 🔘 ความหมาย: AJAX ดึงข้อมูลจำนวนเล็กน้อยแบบอะซิงโครนัส และรีเฟรชเฉพาะบางส่วนของหน้าเว็บเท่านั้น
  • ☑️ ปัญหาหลัก: เวลาตอบสนองของเซิร์ฟเวอร์ไม่แน่นอน ดังนั้นองค์ประกอบดังกล่าวอาจไม่มีอยู่เมื่อ WebDriver ตรวจสอบ
  • ตัวเลือกการรอ: Thread.sleep, implicit wait, explicit wait, WebDriverWait และ FluentWait แต่ละอย่างมีพฤติกรรมที่แตกต่างกัน
  • 🧪 ที่แนะนำ: WebDriverWait ที่ใช้ ExpectedCondition จะตรวจสอบไปเรื่อยๆ จนกว่าผลลัพธ์จาก AJAX จะปรากฏขึ้น จากนั้นจึงดำเนินการต่อทันที
  • 🛠️ FluentWait: ฟังก์ชันนี้จะเพิ่มช่วงเวลาการตรวจสอบ และสามารถละเว้นข้อยกเว้นที่เลือกไว้ระหว่างการลองแต่ละครั้งได้
  • ⚠️ Selenium 4: ตอนนี้การหมดเวลาจะใช้ระยะเวลา และ Selenium ผู้จัดการลบเส้นทางไดรเวอร์แบบกำหนดเองออก

วิธีจัดการกับการเรียกใช้ AJAX ใน Selenium ไดรเวอร์เว็บ

AJAX คืออะไร?

AJAX ย่อมาจาก Asynchronous JavaScript และ XML ช่วยให้เว็บเพจสามารถดึงข้อมูลจำนวนเล็กน้อยจากเซิร์ฟเวอร์ได้โดยไม่ต้องโหลดหน้าเว็บใหม่ทั้งหมด

AJAX เป็นเทคนิคสำหรับการสร้างเว็บเพจที่รวดเร็วและไดนามิก เป็นแบบอะซิงโครนัสและผสมผสานการทำงานต่างๆ เข้าด้วยกัน Javaต้นฉบับ โดยใช้รูปแบบข้อมูล และอัปเดตเฉพาะบางส่วนของหน้าเว็บ แทนที่จะอัปเดตทั้งหน้าเว็บ Gmail, Google แผนที่ เฟซบุ๊ก และ YouTube ทุกคนใช้มัน

AJAX ทำงานอย่างไร?

ตัวอย่างเช่น เมื่อคุณคลิกปุ่มส่งข้อมูล Javaสคริปต์จะส่งคำขอไปยังเซิร์ฟเวอร์ ตีความผลลัพธ์ และอัปเดตหน้าจอปัจจุบันโดยไม่ต้องโหลดหน้าเว็บใหม่ แผนภาพด้านล่างแสดงการแลกเปลี่ยนข้อมูลดังกล่าว

แผนภาพแสดงการเรียกใช้ AJAX ระหว่างเบราว์เซอร์และเซิร์ฟเวอร์โดยไม่ต้องโหลดหน้าเว็บใหม่ทั้งหมด

  • การเรียกใช้ AJAX คือการร้องขอแบบอะซิงโครนัสจากเบราว์เซอร์ ซึ่งไม่ทำให้เกิดการเปลี่ยนหน้าเว็บ ผู้ใช้สามารถทำงานในแอปพลิเคชันต่อไปได้ในขณะที่การร้องขอรอการตอบกลับ
  • AJAX ส่งคำขอ HTTP ไปยังเซิร์ฟเวอร์และประมวลผลการตอบกลับโดยไม่ต้องโหลดหน้าเว็บใหม่ ดังนั้นคุณจึงไม่สามารถคาดเดาได้ว่าเซิร์ฟเวอร์จะใช้เวลานานแค่ไหนในการตอบกลับ

จากมุมมองของผู้ทดสอบ การตรวจสอบเนื้อหาหรือองค์ประกอบหมายถึงการรอจนกว่าจะได้รับคำตอบ ข้อมูลที่ส่งมานั้นเดิมทีเป็น XML ดังที่ชื่อบ่งบอก แต่ปัจจุบัน API ส่วนใหญ่ส่งข้อมูลกลับมาในรูปแบบ JSON

วิธีจัดการกับการโทรเข้า AJAX Selenium ไดรเวอร์เว็บ

ความท้าทายที่ใหญ่ที่สุดในการจัดการกับการเรียกใช้ AJAX คือการทราบเวลาในการโหลด เนื่องจากกระบวนการอัปเดตใช้เวลาเพียงเสี้ยววินาที การทดสอบแอปพลิเคชันด้วยเครื่องมืออัตโนมัติจึงทำได้ยาก Selenium WebDriver ต้องใช้เมธอด wait ในการเรียกใช้งาน

การเรียกใช้คำสั่งรอจะระงับการทำงานปัจจุบัน กรณีทดสอบ จนกว่าค่าที่คาดหวังหรือค่าใหม่จะปรากฏขึ้น Selenium จากนั้น WebDriver จะดำเนินการขั้นตอนที่หยุดชั่วคราวต่อ

ต่อไปนี้เป็นวิธีการรอที่ Selenium WebDriver สามารถใช้งานได้

Thread.sleep()

  • Thread.sleep() ไม่ใช่ทางเลือกที่ดีนัก เพราะมันจะระงับการทำงานของเธรดปัจจุบันตามระยะเวลาที่กำหนด
  • ใน AJAX คุณไม่สามารถแน่ใจได้เลยว่าเวลาการรอที่แน่นอนจะเป็นอย่างไร ดังนั้นการทดสอบจะล้มเหลวหากองค์ประกอบนั้นไม่ปรากฏอยู่ในช่วงเวลาดังกล่าว นอกจากนี้ยังเพิ่มภาระการทำงาน เนื่องจาก Thread.sleep(t) จะย้ายเธรดปัจจุบันจากคิวที่กำลังทำงานไปยังคิวที่รออยู่
  • หลังจากเวลา 't' เธรดจะย้ายไปยังคิวพร้อมทำงาน จากนั้นจะรออีกครั้งเพื่อให้ CPU เลือกไปทำงานต่อ

หมายเหตุ Java วิธีการคือ Thread.sleep() ใช้ตัวพิมพ์เล็กเท่านั้น รูปแบบตัวพิมพ์ใหญ่ไม่สามารถคอมไพล์ได้

รอโดยนัย ()

  • วิธีการนี้จะบอกให้ WebDriver รอเมื่อไม่พบองค์ประกอบที่ต้องการค้นหาในทันที และการตั้งค่านี้จะคงอยู่ตลอดเซสชันการใช้งานเบราว์เซอร์ ดังนั้น การค้นหาองค์ประกอบแต่ละครั้งจึงสามารถใช้เวลานานเท่าที่การรอโดยปริยายอนุญาตได้

รออย่างชัดเจน ()

  • การรอคอยที่ชัดเจน ใช้เพื่อหยุดการดำเนินการทดสอบจนถึงเวลาที่ตรงตามเงื่อนไขเฉพาะหรือช่วงเวลาสูงสุด

เว็บไดร์เวอร์รอสักครู่

  • สามารถใช้ได้กับทุกเงื่อนไข โดยการรวม WebDriverWait เข้ากับ ExpectedCondition
  • วิธีที่ดีที่สุดคือตรวจสอบเงื่อนไขทุกวินาทีและดำเนินการคำสั่งถัดไปทันทีที่ตรงตามเงื่อนไข

แต่ปัญหาของการรอเหล่านี้คือ คุณต้องพูดถึงหน่วยการหมดเวลา จะเกิดอะไรขึ้นถ้าองค์ประกอบนั้นยังไม่ปรากฏภายในเวลานั้น? จึงมีอีกสิ่งหนึ่งที่เรียกว่าการรอคอยอย่างคล่องแคล่ว

รอได้อย่างคล่องแคล่ว

  • นี่คือการใช้งานอินเทอร์เฟซ Wait ที่มีการกำหนดเวลาหมดอายุและช่วงเวลาการตรวจสอบของตัวเอง โดยแต่ละอินสแตนซ์ของ FluentWait จะกำหนดเวลาสูงสุดที่จะรอเงื่อนไขและกำหนดความถี่ในการตรวจสอบเงื่อนไขนั้น

ความท้าทายในการจัดการการเรียกใช้ AJAX Selenium ไดรเวอร์เว็บ

  • การใช้คำสั่ง “หยุดชั่วคราว” นั้นไม่น่าเชื่อถือ การหยุดชั่วคราวเป็นเวลานานจะทำให้การทดสอบช้าลงจนรับไม่ได้และเพิ่มความเสี่ยง การทดสอบ ดังนั้นจึงแนะนำให้ใช้ "waitforcondition" สำหรับแอปพลิเคชัน AJAX แทน
  • เป็นการยากที่จะประเมินความเสี่ยงที่เกี่ยวข้องกับแอปพลิเคชัน AJAX เฉพาะเจาะจง
  • การอนุญาตให้นักพัฒนาแก้ไขแอปพลิเคชัน AJAX ได้อย่างเต็มที่ ทำให้กระบวนการทดสอบมีความท้าทายมากขึ้น
  • การสร้างคำขอทดสอบอัตโนมัติอาจเป็นเรื่องยากสำหรับเครื่องมือทดสอบ เนื่องจากแอปพลิเคชัน AJAX มักใช้เทคนิคการเข้ารหัสหรือการแปลงข้อมูลที่แตกต่างกันในการส่งข้อมูล POST

หมายเหตุ “pause” และ “waitforcondition” คือ เซเลเนเซ คำสั่งถูกลบออกใน 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 ร่วมกับตัวระบุตำแหน่งแบบหมุน การรอเฉพาะองค์ประกอบเป้าหมายอย่างเดียวมักจะผ่านไปเร็วเกินไป ในขณะที่โอเวอร์เลย์ยังคงปิดกั้นการคลิกอยู่

เรียกใช้สคริปต์ `return jQuery.active == 0` ภายในบล็อก `wait until` มันจะแสดงค่าศูนย์ก็ต่อเมื่อไม่มีคำขอ jQuery ใดที่ยังเปิดอยู่

การตอบสนองของ AJAX ได้แทนที่โหนด DOM ที่ WebElement ของคุณชี้ไปแล้ว ให้ค้นหาองค์ประกอบนั้นอีกครั้งหลังจากรอครบเวลาแล้ว แทนที่จะใช้การอ้างอิงเดิมซ้ำ

โมเดล AI เรียนรู้จังหวะเวลาตอบสนองโดยทั่วไปเพื่อปรับเวลารอต่อองค์ประกอบแต่ละส่วน ระบุความล้มเหลวที่เกิดขึ้นเป็นครั้งคราวแทนที่จะเป็นความล้มเหลวที่แท้จริง และจัดกลุ่มความล้มเหลวเหล่านั้นเข้าด้วยกันเพื่อให้สามารถแก้ไขสาเหตุหลักได้ในครั้งเดียว

ใช่. นักบิน GitHub ร่างบล็อก WebDriverWait และ FluentWait จากความคิดเห็น แต่ยืนยันว่า ExpectedCondition ตรงกับพฤติกรรมจริงของหน้าเว็บ

ลำดับ Selenium เอกสารเตือนว่าการผสมผสานวิธีการเหล่านี้อาจทำให้เกิดการหมดเวลาที่ไม่สามารถคาดเดาได้ ควรตั้งค่าการรอโดยปริยายไว้ที่ศูนย์ และใช้การรอโดยระบุอย่างชัดเจนแทน

ไม่ตั้งแต่ Selenium 4.6. Selenium ตัวจัดการจะดาวน์โหลดและกำหนดค่าไดรเวอร์ที่ตรงกัน ดังนั้นบรรทัดนี้จึงจำเป็นเฉพาะสำหรับการกำหนดไบนารีไดรเวอร์ในเครื่องเท่านั้น

สรุปโพสต์นี้ด้วย: