AJAX 호출을 처리하는 방법 Selenium 웹드라이버

⚡ 스마트 요약

AJAX 호출은 페이지를 새로 고침하지 않고 페이지의 일부를 업데이트합니다. Selenium WebDriver는 새 콘텐츠가 이미 존재한다고 가정하는 대신 새 콘텐츠가 나타날 때까지 기다려야 하며, 이러한 대기 전략에 따라 테스트가 안정적으로 통과하는지 여부가 결정됩니다.

  • 🔘 정의: AJAX는 소량의 데이터를 비동식으로 가져와 페이지의 일부만 새로 고칩니다.
  • ☑️ 핵심 문제: 서버 응답 시간을 알 수 없으므로 WebDriver가 해당 요소를 찾을 때 요소가 존재하지 않을 수 있습니다.
  • 대기 옵션: Thread.sleep, implicit wait, explicit wait, WebDriverWait 및 FluentWait는 각각 다르게 동작합니다.
  • 🧪 권장 사항 : ExpectedCondition을 사용하는 WebDriverWait는 AJAX 결과가 나타날 때까지 대기한 후 즉시 계속 진행합니다.
  • 🛠️ 플루언트웨이트: 이 기능은 폴링 간격을 추가하고 시도 사이에 선택된 예외를 무시할 수 있습니다.
  • ⚠️ Selenium 4: 이제 타임아웃은 지속 시간을 가지며, Selenium 관리자가 수동 드라이버 경로를 제거합니다.

AJAX 호출을 처리하는 방법 Selenium 웹드라이버

AJAX란 무엇입니까?

AJAX는 비동기를 의미합니다. Java스크립트와 XML을 사용하며, 웹 페이지가 전체 페이지를 다시 로드하지 않고도 서버에서 소량의 데이터를 가져올 수 있도록 합니다.

AJAX는 빠르고 동적인 웹 페이지를 구축하기 위한 기술입니다. 비동기 방식으로 작동하며, 여러 요소를 결합합니다. JavaScript 데이터 형식을 사용하여 전체 페이지가 아닌 페이지의 일부를 업데이트합니다. Gmail, Google 지도, 페이스북 그리고 YouTube 모두가 그것을 사용합니다.

AJAX는 어떻게 작동하나요?

예를 들어, 제출 버튼을 클릭하면, Java스크립트는 서버에 요청을 보내고, 결과를 해석한 후 화면을 새로 고침하지 않고 현재 화면을 업데이트합니다. 아래 다이어그램은 이러한 과정1을 보여줍니다.

페이지 전체 새로 고침 없이 브라우저와 서버 간의 AJAX 호출을 나타내는 다이어그램

  • AJAX 호출은 페이지 전환을 발생시키지 않는 브라우저의 비동기 요청입니다. 사용자는 요청에 대한 응답을 기다리는 동안에도 애플리케이션에서 계속 작업할 수 있습니다.
  • AJAX는 서버에 HTTP 요청을 보내고 페이지를 새로 고침하지 않고 응답을 처리하므로 서버가 응답하는 데 걸리는 시간을 예측할 수 없습니다.

테스터의 관점에서 콘텐츠나 요소를 확인하는 것은 응답이 도착할 때까지 기다리는 것을 의미합니다. 이름에서 알 수 있듯이 원래 페이로드는 XML이었지만, 현재 대부분의 API는 JSON을 반환합니다.

AJAX 호출을 처리하는 방법 Selenium 웹드라이버

AJAX 호출을 처리할 때 가장 큰 어려움은 로딩 시간을 파악하는 것입니다. 업데이트가 순식간에 이루어지기 때문에 자동화 도구를 통한 테스트가 어렵습니다. Selenium WebDriver는 호출에 대기 메서드를 적용해야 합니다.

해당 대기 명령을 실행하면 현재 작업이 일시 중단됩니다. 테스트 케이스 예상 값 또는 새로운 값이 나타날 때까지. Selenium 그러면 WebDriver는 중단되었던 단계를 다시 시작합니다.

다음은 대기 방법입니다. Selenium WebDriver는 사용할 수 있습니다.

스레드.수면()

  • `Thread.sleep()`는 지정된 시간 동안 현재 스레드를 일시 중단시키므로 현명한 선택이 아닙니다.
  • AJAX에서는 정확한 대기 시간을 확신할 수 없으므로 요소가 테스트 범위 내에 나타나지 않으면 테스트가 실패합니다. 또한 Thread.sleep(t)는 현재 스레드를 실행 큐에서 대기 큐로 이동시키므로 오버헤드가 발생합니다.
  • 't'라는 시간이 지나면 스레드는 준비 큐로 이동하고, CPU가 처리하기를 다시 기다립니다.

참고 : 전에, Java 방법은 스레드.수면() 소문자로 작성해야 합니다. 대문자로 작성하면 컴파일되지 않습니다.

암시적 대기()

  • 이 메서드는 WebDriver에게 요소가 즉시 사용 가능할 때 대기하도록 지시하며, 이 설정은 브라우저 세션 전체에 걸쳐 유지됩니다. 따라서 모든 요소 검색은 암시적 대기 시간만큼 오래 걸릴 수 있습니다.

명시적 대기()

  • 명시적 대기 특정 조건이 충족되거나 최대 시간이 경과할 때까지 테스트 실행을 정지하는 데 사용됩니다.

WebDriver대기

  • WebDriverWait와 ExpectedCondition을 조합하여 어떤 조건에도 사용할 수 있습니다.
  • 가장 좋은 방법은 매초마다 조건을 확인하고 조건이 충족되면 즉시 다음 명령으로 넘어가는 것입니다.

하지만 이러한 모든 대기의 문제는 시간 초과 단위를 언급해야 한다는 것입니다. 해당 요소가 시간 내에 여전히 존재하지 않으면 어떻게 되나요? 따라서 Fluent wait라는 대기가 하나 더 있습니다.

유창한 대기

  • 이 클래스는 자체 타임아웃 및 폴링 간격을 가진 Wait 인터페이스의 구현체입니다. 각 FluentWait 인스턴스는 조건이 충족될 때까지 기다릴 최대 시간과 조건을 확인하는 빈도를 설정합니다.

AJAX 호출 처리 시 발생하는 문제점 Selenium 웹드라이버

  • "pause" 명령어를 사용하는 것은 신뢰할 수 없습니다. 긴 일시 정지는 테스트 속도를 허용할 수 없을 정도로 느리게 만들고 오류를 증가시킵니다. 지원 시간이 오래 걸리기 때문에 AJAX 애플리케이션에서는 "waitforcondition"을 사용하는 것이 권장되었습니다.
  • 특정 AJAX 애플리케이션과 관련된 위험을 평가하기는 어렵습니다.
  • 개발자에게 AJAX 애플리케이션을 수정할 수 있는 완전한 자유를 주면 테스트 과정이 어려워집니다.
  • AJAX 애플리케이션은 POST 데이터를 전송할 때 종종 다른 인코딩 또는 직렬화 기법을 사용하기 때문에 자동화된 테스트 요청을 생성하는 것은 테스트 도구에 어려움을 줄 수 있습니다.

참고 : “일시 중지”와 “조건 대기”는 셀레네세 명령어가 제거되었습니다 Selenium 3; WebDriver에서 이에 해당하는 것은 명시적 대기입니다.

Code AJAX 처리 예시 Selenium 웹드라이버

The 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)를 전달하고 implicitlyWait, pageLoadTimeout 및 모든 FluentWait 설정에 Duration을 사용하십시오.

스피너 로케이터와 함께 ExpectedConditions.invisibilityOfElementLocated를 사용하세요. 대상 요소가 나타날 때까지 기다리는 것만으로는 오버레이가 클릭을 차단하는 동안 너무 빨리 클릭이 완료되지 않는 경우가 많습니다.

`return jQuery.active == 0` 스크립트를 `wait until` 블록 내에서 실행하세요. 이렇게 하면 더 이상 열려 있는 jQuery 요청이 없을 때만 0이 반환됩니다.

AJAX 응답이 WebElement가 가리키던 DOM 노드를 대체했습니다. 이전 참조를 재사용하지 말고 잠시 기다린 후 해당 요소를 다시 찾으세요.

AI 모델은 일반적인 응답 시간을 학습하여 요소별 대기 시간을 조정하고, 진정한 오류가 아닌 간헐적인 오류를 표시하며, 오류를 그룹화하여 근본 원인 하나만 한 번에 해결할 수 있도록 합니다.

예. GitHub 부조종사 WebDriverWait 및 FluentWait 블록의 초안을 댓글에서 가져오지만, ExpectedCondition이 실제 페이지 동작과 일치하는지 확인합니다.

그렇지 않습니다. Selenium 문서에는 이러한 방식을 혼합하면 예측할 수 없는 시간 초과가 발생할 수 있다고 경고합니다. 암시적 대기 시간은 0으로 유지하고 명시적 대기 시간을 사용하십시오.

이후 Selenium 4.6. Selenium 관리자가 일치하는 드라이버를 다운로드하고 구성하므로 해당 줄은 로컬 드라이버 바이너리를 고정하기 위해서만 필요합니다.

이 게시물을 요약하면 다음과 같습니다.