So verarbeiten Sie AJAX-Aufrufe in Selenium Webtreiber

⚡ Intelligente Zusammenfassung

AJAX-Aufrufe aktualisieren einen Teil einer Seite, ohne dass diese neu geladen werden muss, also Selenium WebDriver muss auf den neuen Inhalt warten, anstatt davon auszugehen, dass er vorhanden ist, und die Wartestrategie entscheidet darüber, ob der Test zuverlässig bestanden wird.

  • 🔘 Definition: AJAX ruft kleine Datenmengen asynchron ab und aktualisiert nur einen Teil der Seite.
  • ☑️ Kernproblem: Da die Serverantwortzeit unbekannt ist, existiert das Element möglicherweise nicht, wenn WebDriver danach sucht.
  • ✅ Warteoptionen: Thread.sleep, implizites Warten, explizites Warten, WebDriverWait und FluentWait verhalten sich jeweils unterschiedlich.
  • 🧪 Empfohlen: WebDriverWait mit einer ExpectedCondition fragt so lange ab, bis das AJAX-Ergebnis erscheint, und fährt dann sofort fort.
  • ️ FluentWait: Es fügt ein Abfrageintervall hinzu und kann ausgewählte Ausnahmen zwischen den Versuchen ignorieren.
  • ⚠️ Selenium 4: Timeouts benötigen nun die Dauer Duration, Selenium Der Manager entfernt den manuellen Treiberpfad.

Wie man AJAX-Aufrufe in Selenium WebTreiber

Was ist AJAX?

AJAX steht für Asynchronous JavaScript & XML, und es ermöglicht der Webseite, kleine Datenmengen vom Server abzurufen, ohne die gesamte Seite neu laden zu müssen.

AJAX ist eine Technik zum Erstellen schneller, dynamischer Webseiten. Sie ist asynchron und kombiniert JavaSkript mit einem Datenformat und aktualisiert Teile einer Seite anstatt der gesamten Seite. Gmail, Google Karten, Facebook und YouTube Alle benutzen es.

Wie funktioniert AJAX?

Wenn Sie beispielsweise auf eine Schaltfläche „Absenden“ klicken, JavaDas Skript sendet eine Anfrage an den Server, interpretiert das Ergebnis und aktualisiert den aktuellen Bildschirm ohne Neuladen. Das folgende Diagramm veranschaulicht diesen Vorgang.

Diagramm eines AJAX-Aufrufs zwischen Browser und Server ohne vollständiges Neuladen der Seite

  • Ein AJAX-Aufruf ist eine asynchrone Anfrage des Browsers, die keinen Seitenwechsel auslöst. Der Benutzer kann während der Wartezeit auf die Antwort weiter mit der Anwendung arbeiten.
  • AJAX sendet HTTP-Anfragen an den Server und verarbeitet die Antwort, ohne die Seite neu zu laden. Daher lässt sich nicht vorhersagen, wie lange der Server für eine Antwort benötigt.

Aus Sicht eines Testers bedeutet die Prüfung von Inhalten oder Elementen, auf die Antwort zu warten. Die Nutzdaten waren ursprünglich XML, wie der Name schon sagt; die meisten APIs liefern mittlerweile JSON zurück.

So verarbeiten Sie AJAX-Aufrufe in Selenium WebTreiber

Die größte Herausforderung bei der Verarbeitung eines AJAX-Aufrufs besteht darin, die Ladezeit zu kennen. Da die Aktualisierung nur einen Bruchteil einer Sekunde dauert, ist die Anwendung mit einem Automatisierungstool schwer zu testen. Selenium WebDriver muss eine Wartemethode auf den Aufruf anwenden.

Durch Ausführen dieses Wartebefehls wird der aktuelle Prozess angehalten. Testfall bis der erwartete oder neue Wert erscheint; Selenium WebDriver setzt dann die unterbrochenen Schritte fort.

Im Folgenden sind die Wartemethoden aufgeführt, die Selenium WebDriver kann verwenden

Thread.sleep()

  • Thread.sleep() ist keine gute Wahl, da es den aktuellen Thread für die angegebene Zeitspanne anhält.
  • Bei AJAX lässt sich die genaue Wartezeit nie genau vorhersagen, daher schlägt der Test fehl, wenn das Element nicht innerhalb der Wartezeit erscheint. Außerdem verursacht es zusätzlichen Aufwand, da `Thread.sleep(t)` den aktuellen Thread von der Ausführungswarteschlange in die Warteschlange verschiebt.
  • Nach Ablauf der Zeit 't' wird der Thread in die Warteschlange für bereite Threads eingereiht und wartet dann erneut darauf, von der CPU abgeholt zu werden.

Hinweis: die Java Methode ist Thread.sleep() in Kleinbuchstaben; die großgeschriebene Form kompiliert nicht.

Implizites Wait()

  • Diese Methode weist WebDriver an, zu warten, wenn ein Element nicht sofort verfügbar ist, und diese Einstellung bleibt für die gesamte Browsersitzung bestehen. Jede Elementsuche kann daher so lange dauern, wie die implizite Wartezeit zulässt.

Explizites Wait()

  • Explizites Warten wird verwendet, um die Testausführung einzufrieren, bis eine bestimmte Bedingung erfüllt ist oder die maximale Zeit verstrichen ist.

WebDriverWarten

  • Es kann für jede beliebige Bedingung verwendet werden, indem WebDriverWait mit einer ExpectedCondition kombiniert wird.
  • Die beste Vorgehensweise ist, die Bedingung jede Sekunde zu überprüfen und zum nächsten Befehl überzugehen, sobald sie erfüllt ist.

Aber das Problem bei all diesen Wartezeiten ist, dass man die Zeitüberschreitungseinheit erwähnen muss. Was ist, wenn das Element innerhalb der Zeit immer noch nicht vorhanden ist? Es gibt also noch eine weitere Wartezeit namens Fluent Wait.

Fließend warten

  • Dies ist eine Implementierung der Wait-Schnittstelle mit eigenem Timeout und Abfrageintervall. Jede FluentWait-Instanz legt die maximale Wartezeit für eine Bedingung und die Häufigkeit der Überprüfung fest.

Herausforderungen bei der Verarbeitung von AJAX-Anrufen Selenium WebTreiber

  • Die Verwendung des Befehls „Pause“ ist unzuverlässig. Eine lange Pause verlangsamt den Test inakzeptabel und erhöht die Laufzeit. Tests Da dies zeitlich begrenzt war, wurde für AJAX-Anwendungen stattdessen „waitforcondition“ empfohlen.
  • Es ist schwierig, das mit bestimmten AJAX-Anwendungen verbundene Risiko einzuschätzen.
  • Die uneingeschränkte Freiheit der Entwickler, eine AJAX-Anwendung zu modifizieren, macht den Testprozess anspruchsvoll.
  • Das Erstellen einer automatisierten Testanfrage kann für Testwerkzeuge schwierig sein, da AJAX-Anwendungen oft eine andere Kodierungs- oder Serialisierungstechnik verwenden, um POST-Daten zu übermitteln.

Hinweis: „pause“ und „waitforcondition“ sind Selenese Befehle entfernt in Selenium 3; das WebDriver-Äquivalent ist ein explizites Warten.

Code Beispiel für die AJAX-Verarbeitung mit Selenium WebTreiber

Das TestNG Die unten stehende Klasse liest den Text, klickt auf den Optionsknopf, wartet auf die AJAX-Antwort und stellt fest, dass sich der Text geändert hat.

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

Hinweis: on Selenium 4 Pass Dauer.inSekunden(5) WebDriverWait und die Zeile System.setProperty entfernen, weil Selenium Manager löst chromedriver auf.

Häufig gestellte Fragen

Nein. Die Konstruktoren `int` und `long` wurden entfernt. Verwenden Sie stattdessen `Duration.ofSeconds(5)` und `Duration` für `implicitlyWait`, `pageLoadTimeout` und alle `FluentWait`-Einstellungen.

Verwenden Sie `ExpectedConditions.invisibilityOfElementLocated` zusammen mit dem Spinner-Locator. Das alleinige Warten auf das Zielelement ist oft zu früh abgeschlossen, solange das Overlay den Klick noch blockiert.

Führe das Skript `return jQuery.active == 0` innerhalb eines `wait until`-Blocks aus. Es gibt nur dann Null zurück, wenn keine jQuery-Anfrage mehr offen ist.

Die AJAX-Antwort hat den DOM-Knoten, auf den Ihr WebElement verwies, überschrieben. Suchen Sie das Element nach der Wartezeit erneut, anstatt die vorherige Referenz wiederzuverwenden.

KI-Modelle lernen typische Reaktionszeiten, um Wartezeiten pro Element zu optimieren, intermittierende statt echter Fehler zu kennzeichnen und diese zu gruppieren, sodass eine Ursache nur einmal behoben werden muss.

Ja. GitHub-Copilot Entwirft WebDriverWait- und FluentWait-Blöcke aus einem Kommentar, aber bestätigt, dass die ExpectedCondition mit dem tatsächlichen Seitenverhalten übereinstimmt.

Nein. Selenium Die Dokumentation warnt davor, dass die Kombination beider Methoden zu unvorhersehbaren Timeouts führen kann. Halten Sie die implizite Wartezeit bei null und verwenden Sie ausschließlich explizite Wartezeiten.

Nicht seit Selenium 4.6 Selenium Der Manager lädt einen passenden Treiber herunter und konfiguriert ihn, daher ist die Zeile nur erforderlich, um eine lokale Treiber-Binärdatei festzulegen.

Fassen Sie diesen Beitrag mit folgenden Worten zusammen: