Dieser Artikel wird tiefer in den Umgang mit Popups mit Selenium Webdriver eintauchen und sie automatisieren. Dies ist ein Blogbeitrag von Mark Collin auf EuroSTAR Huddle, unserer Online-Community für kostenlose Softwaretestressourcen.
Entmystifizierung von Popups mit Selenium
Nachdem Sie eine Weile mit Selenium gearbeitet haben, erhalten Sie schließlich die Aufgabe, etwas zu automatisieren, das eine Art Popup-Funktionalität hat. Popups können in Selenium ein heikles Thema sein, da die Definition dessen, was ein Popup ist, unklar sein kann und verschiedene Treiber ein unterschiedliches Standardverhalten aufweisen. In diesem Artikel werde ich versuchen, einige klare Definitionen verschiedener Popups bereitzustellen, Ihnen zu zeigen, wie Sie mit Popups in Selenium Webdriver umgehen, und Ihnen zeigen, wie Sie sie automatisieren, sowie ein paar Fallstricke.
Zuerst müssen wir definieren, was wir unter einem Popup verstehen; Es ist ein nebulöser Begriff, den Leute verwenden, um mehrere verschiedene Arten von Funktionalität zu beschreiben, die in freier Wildbahn sind. Ich unterteile Popups gerne in drei Hauptkategorien:
Popups auf Betriebssystemebene
Das erste aufgelistete Popup ist ein Dialog auf Betriebssystemebene; Dies sind die Dinge, die Sie sehen werden, wenn der Browser die Kontrolle an das Betriebssystem übergibt, um eine Aufgabe dafür zu erledigen (obwohl Browser wie Chrome die Grenzen hier ein wenig verwischen, indem sie es so aussehen lassen, als würde der Browser es tun). Sie werden diese normalerweise sehen, wenn Sie etwas tun, was der Browser nicht kann. An diesem Punkt übergibt der Browser an das Betriebssystem, um ein anderes Programm zu finden, um die erforderliche Aufgabe auszuführen. Einige Beispiele für diese Dinge sind:
- Drucken einer Seite, die Sie im Browser anzeigen.
- Versenden eines Links als E-Mail.
- Herunterladen einer Datei.
Die beste Option, um mit diesen Popups auf Betriebssystemebene umzugehen, besteht darin, niemals etwas zu tun, das sie in Ihrem Test auslöst. Das Selenium-Tutorial ist nur für die Interaktion mit gerenderten Websites konzipiert
der Browser, die Steuerung des Betriebssystems ist völlig außerhalb des Bereichs. Wenn Sie versuchen wollten, mit diesen Popups auf Betriebssystemebene zu interagieren, müssten Sie einen Code schreiben, der die steuern kann
Betriebssystem selbst (z. B. etwas, das die Java Robot-Klassen verwendet). Es gibt Tools, die dies tun, aber es ist ein komplexes Stück Arbeit, und Sie müssen die Funktionalität auf Betriebssystemebene wirklich nicht testen, um zu überprüfen, ob Ihre Website funktioniert.
HTML-Popups (Leuchtkästen)
Ein HTML-Popup kann wie ein JavaScript-Popup oder ein Popup auf Betriebssystemebene aussehen, aber in Wirklichkeit ist es nur mehr HTML, das über dem vorhandenen HTML auf der Website geschichtet ist. Aufgrund der Tatsache, dass diese Popups HTML sind, können Website-Designer CSS verwenden, um diese Dinge wie etwas aussehen zu lassen, das sie nicht sind, was zu Verwirrung führen kann. Sie müssen nichts Besonderes tun, um damit zu arbeiten; schließlich sind sie nur HTML und CSS. Sie interagieren einfach mit ihnen auf die gleiche Weise wie mit jedem anderen Element auf dem Bildschirm und tun dann, was Sie wollen.
JavaScript-Popups
Dies sind blockierende Popups; Sie unterbrechen die Ausführung von JavaScript, bis mit ihnen interagiert wurde. In der Vergangenheit waren dies die Standardtypen von Selenium-Popups, obwohl sie heutzutage nicht mehr ganz so verbreitet sind, da Website-Designer dazu neigen, stattdessen nicht blockierende HTML-Popups zu verwenden. Dies sind Dinge, mit denen Selenium interagieren kann, aber Sie müssen im Voraus wissen, welche Aktionen diese Popups auslösen werden.
Wir sollten jetzt eine klare Vorstellung von den verschiedenen Arten von Popups haben. Als nächstes schauen wir uns etwas Code an.
Arbeiten mit Warnungen
Zunächst werden wir uns ansehen, wie Sie Warnmeldungen automatisieren können. Zunächst benötigen wir etwas HTML zur Automatisierung. Speichern Sie den folgenden HTML-Code als „alert.html“:
private Zeichenfolge alertFileLocation = “file://
Warnungen in Selen
Dies ist eine einfache Seite mit einigen Schaltflächen. Einer löst eine HTML-Warnung aus und einer löst eine JavaScript-Warnung aus. Laden Sie es in den Browser und probieren Sie es aus, um zu sehen, wie es funktioniert.
Wir werden jetzt Code schreiben, um diese Seite zu automatisieren. Zunächst müssen wir den Ort definieren, an dem Sie das obige HTML gespeichert haben. Ersetzen Sie einfach den folgenden Code durch den Pfad zu der Datei, die Sie oben gespeichert haben.
private Zeichenfolge alertFileLocation = “file://
Nun zu unserem ersten grundlegenden Teil der Automatisierung:
@Prüfen public void triggerBothPopups() löst Exception { driver.get (alertFileLocation); WebElement generateAlertOne = driver.findElement(By.id("js_alert")); WebElement generateAlertTwo = driver.findElement(By.id("html_alert")); generateAlertOne.click(); generateAlertTwo.click(); }
Dieser Code lädt die Webseite: Klicken Sie auf die Schaltfläche, um die JavaScript-Warnung auszulösen, und klicken Sie dann auf die Schaltfläche, um die HTML-Warnung auszulösen. Wenn Sie diesen Test jetzt ausführen, sollte er fehlschlagen und Sie sollten einen Fehler sehen, der so aussieht:
org.openqa.selenium.UnhandledAlertException: Unerwartete Warnung geöffnet: {Warntext: Dies ist eine JavaScript-Warnung}
Möglicherweise haben Sie jedoch keinen Fehler gesehen …
Dies liegt daran, dass verschiedene Treiber unterschiedlich implementiert werden; Wenn Sie Firefox v53.0.3 und GeckoDriver v0.16.1 ausführen, hat es die Tatsache ignoriert, dass dort ein Popup angezeigt wird, und versucht, trotzdem fortzufahren. Wir werden später darauf zurückkommen und uns das ansehen. Lassen Sie uns zunächst sicherstellen, dass wir chromedriver verwenden.
Jetzt, da wir Chromedriver verwenden, versuchen wir, unseren Automatisierungscode zu reparieren. Selenium bietet eine API, die es Ihnen ermöglicht, mit Warnungen zu interagieren, also lassen Sie uns sie verwenden.
@Prüfen public void triggerBothPopups() löst Exception { driver.get (alertFileLocation); WebElement generateAlertOne = driver.findElement(By.id("js_alert")); WebElement generateAlertTwo = driver.findElement(By.id("html_alert")); generateAlertOne.click(); driver.switchTo().alert().accept(); generateAlertTwo.click(); driver.switchTo().alert().accept(); }
Wie Sie sehen können, sagen wir Selenium jetzt, dass es auf die Warnung umschalten soll, sobald sie aufgetaucht ist. Sobald wir darauf umgestellt haben, sagen wir Selenium, es zu akzeptieren. Lassen Sie uns den Test erneut ausführen und sehen, was jetzt passiert.
Sie sollten nun den folgenden Fehler sehen:
org.openqa.selenium.NoAlertPresentException: Keine Warnung offen
Dies liegt daran, dass unsere erste Benachrichtigung ein JavaScript-Popup ist, unsere zweite jedoch ein HTML-Popup (oder eine Lightbox). Die Funktion, zu einer Warnung zu wechseln und sie zu akzeptieren, funktioniert nur mit JavaScript-Popups, nicht mit HTML-Popups. Um mit dem HTML-Popup zu interagieren, müssen wir uns das Markup ansehen und damit umgehen wie mit jedem anderen HTML-Element.
Hier ist unser letztes Stück Testcode.
@Prüfen public void triggerBothPopups() löst Exception { driver.get (alertFileLocation); WebElement generateAlertOne = driver.findElement(By.id("js_alert")); WebElement generateAlertTwo = driver.findElement(By.id("html_alert")); generateAlertOne.click(); driver.switchTo().alert().accept(); generateAlertTwo.click(); WebElement closeHtmlAlertButton = driver.findElement(By.cssSelector(.ui-button")); closeHtmlAlertButton.click(); }
Wir behandeln jetzt jede Art von Warnung korrekt und haben ein glückliches Stück Automatisierung.
Warum der Test in Firefox nicht fehlgeschlagen ist
Fahren wir mit unserem Selenium-Tutorial fort und kehren wir zu dem Problem mit Firefox zurück, das wir erwähnt haben, als wir unseren ersten Test geschrieben haben. Firefox löste keine Ausnahme aus, wenn eine unerwartete Warnung vorhanden war, sodass wir keinen Fehler sahen. Wenn so etwas passiert, kann es sehr verwirrend sein. Der Hauptgrund, warum unser Test nicht fehlschlug, war, dass wir danach keine Kontrollen mehr durchführten
Interaktion mit den Elementen. Lassen Sie uns den letzten Test machen, den wir geschrieben haben, und den Code löschen, der zur Warnung wechselt, und sehen, was passiert, wenn wir ihn in Firefox v53.0.3 und GeckoDriver v0.16.1 ausführen.
@Prüfen public void triggerBothPopups() löst Exception { driver.get (alertFileLocation); WebElement generateAlertOne = driver.findElement(By.id("js_alert")); WebElement generateAlertTwo = driver.findElement(By.id("html_alert")); generateAlertOne.click(); generateAlertTwo.click(); WebElement closeHtmlAlertButton = driver.findElement(By.cssSelector(.ui-button")); closeHtmlAlertButton.click(); }
Diesmal schlägt der Test fehl, aber Sie sehen den folgenden Fehler:
org.openqa.selenium.NoSuchElementException: Element kann nicht gefunden werden: .ui-button
Es ist fehlgeschlagen, weil wir die Schaltfläche zum Schließen des HTML-Popups nicht finden können; Die Implikation hier ist, dass das Klicken auf die zweite Schaltfläche zum Generieren von Warnungen nicht funktioniert hat. Jetzt wissen wir, dass dies nicht der Fall ist, dieser Test schlägt fehl, weil wir den Code entfernt haben, der auf die Warnung umschaltet und sie akzeptiert. Können wir dies klarer machen, indem wir einen Screenshot dessen, was der Test sieht, in die Datei schreiben?
@Prüfen public void triggerBothPopups() löst Exception { driver.get (alertFileLocation); WebElement generateAlertOne = driver.findElement(By.id("js_alert")); WebElement generateAlertTwo = driver.findElement(By.id("html_alert")); generateAlertOne.click(); generateAlertTwo.click(); Screenshot der Datei = neue Datei ("screenshot.png"); FileOutputStream screenshotStream = new FileOutputStream(screenshot); screenshotStream.write(((TakeScreenshot) driver).getScreenshotAs(OutputType.BYTES)); ScreenshotStream.close(); System.out.println("Screenshot gespeichert unter: " + screenshot.getAbsolutePath()); WebElement closeHtmlAlertButton = driver.findElement(By.cssSelector(.ui-button")); closeHtmlAlertButton.click(); }
Lassen Sie uns den Test erneut ausführen; Dieses Mal wird ein Screenshot erstellt und der Speicherort der Datei im Konsolenprotokoll angezeigt. Dies sollte uns die JavaScript-Warnung zeigen, die alle Probleme verursacht.
Wenn Sie jetzt den Screenshot öffnen und sich ihn ansehen, wird er Ihnen wahrscheinlich nicht das zeigen, was Sie erwartet haben. Der Screenshot zeigt die gerenderte Website ohne JavaScript- oder HTML-Warnungen. Was ist los?
JavaScript-Popups sind nicht Teil der gerenderten Website, sondern werden vom Browser gerendert. Infolgedessen werden sie nicht in Screenshots von Selenium angezeigt. In jeder Hinsicht sieht es so aus, als hätten wir einen Fehler bei der Website-Implementierung gefunden. Es sieht so aus, als ob das Klicken auf die zweite Schaltfläche keine HTML-Warnung auslöst, die angezeigt werden soll. Wenn Sie jedoch zurückgehen und manuell testen, werden Sie sehen, dass es funktioniert.
Wir kennen das Problem, aber stellen Sie sich vor, wie verwirrend das für jemanden wäre, der nicht versteht, dass wir eine Mischung aus verschiedenen Arten von Popups haben. Sie würden wahrscheinlich einen Fehler melden, der besagt, dass die zweite Schaltfläche nicht funktioniert hat, und ihn an einen Entwickler zurückgeben, der das Problem nicht reproduzieren könnte (weil das einzige vorhandene Problem ein Problem mit dem Testcode ist).
Arbeiten mit anderen Arten von JavaScript-Popups
Bisher haben wir uns nur mit einem Popup-Typ beschäftigt, dem Alert. Es gibt zwei weitere Arten von JavaScript-Popups, auf die Sie möglicherweise stoßen, das Aufforderungs-Popup und das Bestätigungs-Popup. Lassen Sie uns das letzte Stück HTML erstellen, das wir automatisieren werden, speichern Sie Folgendes als „popup.html“:
Eingabeaufforderungen in Selen
Wie zuvor müssen wir den Ort definieren, an dem Sie das obige HTML gespeichert haben. Ersetzen Sie einfach den folgenden Code durch den Pfad zu der Datei, die Sie oben gespeichert haben.
private String popupFileLocation = “file:///popup.html”;
Zunächst schauen wir uns an, wie wir mit einem Bestätigungs-Popup interagieren können. Bestätigungs-Popups stellen Ihnen eine Frage, der Sie entweder zustimmen oder die Sie abbrechen können. Sie haben immer zwei Optionen, „OK“ oder „Abbrechen“. Popups wie dieses werden normalerweise verwendet, um die Codeausführung zu blockieren, bis Sie etwas zustimmen.
Nehmen wir an, dass wir zunächst dem Bestätigungs-Popup zustimmen.
@Prüfen public void triggerJavaScriptConfirmation() löst Exception { driver.get (popupFileLocation); WebElement generateConfirmationPopup = driver.findElement(By.id("js_confirm")); generateConfirmationPopup.click(); driver.switchTo().alert().accept(); }
Der Code ist sehr einfach, tatsächlich ist er genau derselbe wie der Code, den wir verwendet haben, um das Alarm-Popup zu automatisieren. Wenn wir dem Bestätigungs-Popup nicht zustimmen möchten, ist der Code genauso einfach:
@Prüfen public void triggerJavaScriptConfirmation() löst Exception { driver.get (popupFileLocation); WebElement generateConfirmationPopup = driver.findElement(By.id("js_confirm")); generateConfirmationPopup.click(); driver.switchTo().alert().dismiss(); }
Der letzte Popup-Typ, den wir uns ansehen werden, ist die JavaScript-Eingabeaufforderung. Dies sind blockierende Popups, die verwendet werden, um einige Informationen von Ihnen zu erhalten. Wenn Sie diese Art von Popup verwenden, werden Sie dem Benutzer wahrscheinlich eine Frage stellen, auf die er antworten muss, also werden wir uns ansehen, wie wir überprüfen können, ob die richtige Frage gestellt und die erforderlichen Informationen eingegeben werden . Hier ist unser Code:
@Prüfen public void triggerJavaScriptPrompt() löst Exception { driver.get (popupFileLocation); WebElement generatePromptPopup = driver.findElement(By.id("js_prompt")); generatePromptPopup.click(); Alarmaufforderung = driver.switchTo().alert(); assert(prompt.getText().equals("Dies ist eine JavaScript-Eingabeaufforderung, sie möchte einige Informationen erhalten.")); prompt.dismiss(); }
Nachdem wir unsere JavaScript-Eingabeaufforderung ausgelöst haben, haben wir uns diesmal entschieden, ein Alert-Objekt zu definieren. Wir werden mehr als einmal mit der Warnung interagieren, daher ist es sinnvoll, dies für die Klarheit und Sauberkeit des Codes zu tun. Wir haben dann den Befehl getText() verwendet, um den Text abzurufen, der dem Benutzer angezeigt wird, und eine Behauptung aufgestellt, um zu überprüfen, ob er mit unserem erwarteten Text übereinstimmt. Wir haben daraufhin entschieden, dass wir keine weiteren Angaben machen wollen und haben die Warnung zurückgewiesen.
Was wäre, wenn wir uns entschieden hätten, einige Informationen zu übermitteln? In diesem Fall hätten wir folgenden Code geschrieben:
@Prüfen public void triggerJavaScriptPrompt() löst Exception { driver.get (popupFileLocation); WebElement generatePromptPopup = driver.findElement(By.id("js_prompt")); generatePromptPopup.click(); Alarmaufforderung = driver.switchTo().alert(); assert(prompt.getText().equals("Dies ist eine JavaScript-Eingabeaufforderung, sie möchte einige Informationen erhalten.")); prompt.sendKeys("Einige Informationen"); prompt.accept(); }
Wie Sie sehen können, haben wir dieses Mal einige Informationen mit dem Befehl sendKeys () gesendet und dann die Eingabeaufforderung akzeptiert. Wir hätten natürlich trotzdem entscheiden können, die Eingabeaufforderung nach der Eingabe einiger Informationen zu schließen, aber das ist ein Szenario, das wir nicht geschrieben haben. Das könntest du immer selbst ausprobieren.
Es ist noch einmal erwähnenswert, dass verschiedene Treiberimplementierungen auf viele verschiedene Arten agieren können und verschiedene Treiberimplementierungen verschiedene Teile der WebDriver-API unterstützen können. Wenn Sie Probleme haben, lohnt es sich immer, einen anderen Treibertyp auszuprobieren, um zu sehen, ob Ihr Code funktioniert.
**Dieser Blog wurde von Google aus dem Englischen ins Deutsche übersetzt.**