Hvordan håndtere AJAX-anrop inn Selenium Webdriver

⚡ Smart oppsummering

AJAX-kall oppdaterer deler av en side uten å laste inn på nytt, så Selenium WebDriver må vente på det nye innholdet i stedet for å anta at det er til stede, og ventestrategien avgjør om testen består pålitelig.

  • 🔘 Definisjon: AJAX henter små mengder data asynkront og oppdaterer bare deler av siden.
  • ☑️ Kjerneproblem: Serverens responstid er ukjent, så elementet finnes kanskje ikke når WebDriver ser etter.
  • Ventealternativer: Thread.sleep, implisitt vent, eksplisitt vent, WebDriverWait og FluentWait oppfører seg alle forskjellig.
  • 🧪 Anbefalt: WebDriverWait med en ExpectedCondition avspør til AJAX-resultatet vises, og fortsetter deretter umiddelbart.
  • 🛠️ FlytendeVent: Den legger til et avstemningsintervall og kan ignorere valgte unntak mellom forsøk.
  • ⚠️ Selenium 4: Tidsavbrudd tar nå Varighet, og Selenium Manager fjerner den manuelle driverbanen.

Slik håndterer du AJAX-kall i Selenium webdriver

Hva er AJAX?

AJAX står for Asynkron JavaSkript og XML, og det lar nettsiden hente små mengder data fra serveren uten å laste inn hele siden på nytt.

AJAX er en teknikk for å bygge raske, dynamiske nettsider. Den er asynkron og kombinerer JavaScript med et dataformat, og oppdaterer deler av en side i stedet for hele siden. Gmail, Google Kart, Facebook og YouTube alle bruker det.

Hvordan fungerer AJAX?

For eksempel, når du klikker på en send-knapp, JavaSkriptet sender en forespørsel til serveren, tolker resultatet og oppdaterer gjeldende skjermbilde uten å laste det inn på nytt. Diagrammet nedenfor viser denne utvekslingen.

Diagram over et AJAX-kall mellom nettleser og server uten at siden lastes inn på nytt.

  • Et AJAX-kall er en asynkron forespørsel fra nettleseren som ikke forårsaker en sideovergang. Brukeren kan fortsette å jobbe med applikasjonen mens forespørselen venter på svar.
  • AJAX sender HTTP-forespørsler til serveren og behandler svaret uten å laste siden på nytt, så du kan ikke forutsi hvor lang tid det vil ta for serveren å svare.

Fra en testers synspunkt betyr det å sjekke innhold eller et element å vente til svaret kommer. Nyttelasten var opprinnelig XML, som navnet gjenspeiler; de fleste API-er returnerer nå JSON.

Hvordan håndtere AJAX-anrop inn Selenium webdriver

Den største utfordringen med å håndtere et AJAX-kall er å vite lastetiden. Fordi oppdateringen varer en brøkdel av et sekund, er applikasjonen vanskelig å teste gjennom et automatiseringsverktøy, så Selenium WebDriver må bruke en ventemetode på kallet.

Å kjøre den ventekommandoen suspenderer den gjeldende Testsak inntil den forventede eller nye verdien vises; Selenium WebDriver gjenopptar deretter de avbrutte trinnene.

Følgende er ventemetodene som Selenium WebDriver kan bruke

Thread.sleep ()

  • Thread.sleep() er ikke et klokt valg, ettersom det suspenderer den gjeldende tråden i den angitte tiden.
  • I AJAX kan du aldri være sikker på den nøyaktige ventetiden, så testen mislykkes hvis elementet ikke vises i den. Det legger også til overhead, fordi Thread.sleep(t) flytter den gjeldende tråden fra den kjørende køen til den ventende køen.
  • Etter tiden 't' flyttes tråden til klarkøen, og venter deretter igjen på å bli plukket opp av CPU-en.

OBS: de Java metoden er Thread.sleep () med liten bokstav; den store bokstaven kompilerer ikke.

Implisitt vent()

  • Denne metoden forteller WebDriver at den skal vente når et element ikke er tilgjengelig umiddelbart, og innstillingen forblir aktiv gjennom hele nettleserøkten. Hvert elementsøk kan derfor ta så lang tid som den implisitte ventetiden tillater.

Eksplisitt vent()

  • Eksplisitt ventetid brukes til å fryse testkjøringen til tidspunktet en bestemt betingelse er oppfylt eller maksimal tid utløper.

WebDriverWait

  • Den kan brukes for enhver betingelse, ved å kombinere WebDriverWait med en ExpectedCondition.
  • Den beste tilnærmingen er å sjekke betingelsen hvert sekund og gå videre til neste kommando så snart den er oppfylt.

Men problemet med alle disse ventetidene er at du må nevne timeout-enheten. Hva om elementet fortsatt ikke er tilstede innen tiden? Så det er en vent til som heter Fluent wait.

Flytende vent

  • Dette er en implementering av Wait-grensesnittet med sin egen timeout og pollingintervall. Hver FluentWait-instans angir maksimal ventetid for en betingelse og hvor ofte den skal sjekkes.

Utfordringer med å håndtere AJAX-kall Selenium webdriver

  • Det er ikke pålitelig å bruke kommandoen «pause». En lang pause gjør testen uakseptabelt langsom og øker Testing tid, så «waitforcondition» ble anbefalt for AJAX-applikasjoner i stedet.
  • Det er vanskelig å vurdere risikoen forbundet med bestemte AJAX-applikasjoner
  • Å gi utviklere full frihet til å endre en AJAX-applikasjon gjør testprosessen utfordrende
  • Det kan være vanskelig å opprette en automatisert testforespørsel for testverktøy, fordi AJAX-applikasjoner ofte bruker en annen kodings- eller serialiseringsteknikk for å sende inn POST-data.

OBS: «Pause» og «Vent på betingelse» er Selenesisk kommandoer fjernet i Selenium 3; WebDriver-ekvivalenten er en eksplisitt venting.

Code Eksempel på AJAX-håndtering ved bruk av Selenium webdriver

Ocuco TestNG Klassen nedenfor leser teksten, klikker på alternativknappen, venter på AJAX-svaret og bekrefter at teksten er endret.

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();
	}
	
}

OBS: on Selenium 4 bestått Varighet.av sekunder(5) til WebDriverWait og slett System.setProperty-linjen, fordi Selenium Manager løser chromedriver.

Spørsmål og svar

Nei. int- og long-konstruktørene ble fjernet. Send Duration.ofSeconds(5) i stedet, og bruk Duration for implicitlyWait, pageLoadTimeout og alle FluentWait-innstillinger.

Bruk ExpectedConditions.invisibilityOfElementLocated med spinner-lokaliseringsverktøyet. Venting på målelementet alene går ofte for tidlig, mens overlegget fortsatt blokkerer klikket.

Kjør skriptet return jQuery.active == 0 i en wait until-blokk. Det rapporterer null bare når ingen jQuery-forespørsler fortsatt er åpne.

AJAX-svaret erstattet DOM-noden som WebElementet ditt pekte på. Finn elementet på nytt etter ventetiden i stedet for å bruke den tidligere referansen på nytt.

AI-modeller lærer typiske responstider for å finjustere ventetider per element, flagge intermitterende i stedet for ekte feil, og gruppere dem slik at én rotårsak fikses én gang.

Ja. GitHub Copilot lager utkast til WebDriverWait- og FluentWait-blokker fra en kommentar, men bekrefter at ExpectedCondition samsvarer med den faktiske sideoppførselen.

Nei. Selenium Dokumentasjonen advarer om at det å blande dem forårsaker uforutsigbare tidsavbrudd. Hold den implisitte ventetiden på null og stol på eksplisitte ventetider.

Ikke siden Selenium 4.6. Selenium Manager laster ned og konfigurerer en samsvarende driver, slik at linjen bare trengs for å pinne en lokal driverbinærfil.

Oppsummer dette innlegget med: