Implementierung des Prozesses zum Hochladen einer Datei aus einem Container mit einem Browser in ein Testframework

Automatisierung von End-2-End-Tests eines integrierten Informationssystems
Teil 2-2. Implementieren des Prozesses zum Hochladen einer Datei aus einem Container mit einem Browser in ein Testframework. Suchen Sie nach dem Namen der vom Browser heruntergeladenen Datei


Autor: habr.com/us/users/anrad
Hubs:
Tags: #autotest, #selenium, #selenoid, #headlessbrowser, #download


Als wir End-2-End-Autotests für die Benutzeroberfläche entwickelten, standen wir vor der Frage: „Wie erhalte ich den Namen des zuletzt geladenen ? Dateibrowser von WebDriver? ", Google hat nichts schnell erhalten. Deshalb habe ich diesen Artikel geschrieben, in dem gleichzeitig erklärt wurde, was genau wir ein Problem hatten und wie wir es gelöst haben.

Mit diesem Artikel setzen wir eine Reihe von Veröffentlichungen darüber fort, wie wir den Prozess des manuellen Testens (im Folgenden als Autotests bezeichnet) eines großen Informationssystems (im Folgenden als Systeme bezeichnet) in einem der großen LANIT-Projekte automatisiert haben und was daraus entstanden ist.

Bild
Quelle


Der Artikel selbst schließt den Zyklus ab. Unten finden Sie einen Link zu allen vorherigen Teilen:
Teil 1. Organisatorisch und verwaltungstechnisch. Warum brauchten wir Automatisierung? Organisation des Entwicklungs- und Managementprozesses. Nutzungsorganisation
Teil 2. Technisch. Architektur und technischer Stack. Implementierungsdetails und technische Überraschungen
Teil 2-1. Basisklassenimplementierung für alle Tests und JUnit RuleChain.

Das war vor einem Jahr. Daher ist es heute möglicherweise nicht relevant. Schreiben Sie in die Kommentare, wenn Sie wissen, wie Sie Dateien mit mehreren Selenoid-Grid-Servern effizient verarbeiten können.

Bei der Entwicklung von „Autotests“ hatten wir die Aufgabe, Dateien vom System herunterzuladen (herunterzuladen) und anschließend deren Inhalt zu analysieren. Um Dateien vom getesteten System hochzuladen, verwenden wir die folgenden Lösungen:
  • für den "lokalen" Startmodus (direkt auf dem Arbeits-PC starten) - Wenn der "lokale" Browser initialisiert wird, wird der Name des temporären lokalen Ordners als Parameter an ihn übergeben. Als nächstes wird die Datei zur anschließenden Analyse direkt aus dem lokalen Ordner gelesen.
  • für "Remote" -Modus (über Bamboo) - Die Datei wurde mit dem Browser über die Solenoid-Serverfunktion aus dem Container "entnommen": selenoid-host.example.com : 4444 / download / {SESSION_ID} / {FILE_NAME}


Details sind in der Dokumentation beschrieben.

Für beide Modi musste der Name bekannt sein, um auf die Datei zugreifen zu können. Das war eine Überraschung. Das Problem des Mangels an Daten zum Namen der "Download" -Datei war wie folgt:
  • Nach dem Klicken auf die Schaltfläche "Datei herunterladen" hat der Browser die Datei in den entsprechenden lokalen Ordner im Container heruntergeladen.
  • In diesem Fall wurde der Dateiname dynamisch gebildet, und wie man ihn im Voraus bestimmt, konnten wir nicht finden. Dies war ein Merkmal unseres Testsystems;
  • Ferner sollte diese Datei aus dem Container „herausgezogen“ werden und eine geschäftliche Überprüfung ihres Inhalts durchgeführt werden.
  • Um die Datei „herauszuziehen“, sollten Sie ihren Namen kennen, aber wir kannten den Namen nicht, da der Name dynamisch generiert wurde und der Link keinen Wert enthielt.


Darüber hinaus wurde die Situation durch die Tatsache verschärft, dass aufgrund der großen Komplexität einiger Tests mehrere Dateien während des Tests als Teil verschiedener unabhängiger Testskripte aus der Zusammensetzung des Tests selbst entladen werden konnten.
Die beste Lösung für uns war die Methode, mit der wir die zuletzt heruntergeladene Datei ermittelt haben. Es gab verschiedene Möglichkeiten, dies zu tun:
  • . . , ;
  • Google Chrome javascript chrome://downloads/, html-. .




Das Analysieren der Zusammensetzung der vom Browser geladenen Dateien für den lokalen Modus ist eine triviale Aufgabe.
Für den Remote-Modus müssen Sie die Funktion "undokumentiert" des Server-Selenoids verwenden: selenoid-host.example.com : 4444 / download / {SESSION_ID} zeigt eine Liste aller erfolgreich heruntergeladenen Dateien an, wobei SESSION_ID eine Selenoid-Sitzungs-ID ist.
Im Allgemeinen funktioniert das Schema mit einer Ausnahme: we Sie müssen eine Weile warten, bis die Datei heruntergeladen und in der Liste angezeigt wird. Die Wartezeit kann über einen Timeout-Zyklus eingestellt werden. Auf diese Weise können wir jedoch keine Informationen über einen möglichen Fehler beim Hochladen von Dateien erhalten. Wir können nur feststellen, dass die Datei in dieser Schaltung nicht geladen wurde. Daher haben wir uns am Ende für die Methode zur Bestimmung des Dateinamens über die Seite chrome: // downloads / entschieden.

Abrufen des Dateinamens über die chrome: // downloads / page


Diese Methode funktioniert sowohl im lokalen als auch im Remote-Modus gleich gut. Das Arbeitsschema ist recht einfach:
  • Führen Sie das Java-Skript aus, um das Chrome-Fenster zu öffnen: // downloads /;
  • Daten im Fenster wie gewohnt verarbeiten. Warten Sie, bis die erste Datei in der Liste geladen ist, und bestimmen Sie ihren Namen.
  • Schließen Sie das Fenster chrome: // downloads / und geben Sie den Namen der gesuchten Datei zurück.


Wir haben die Idee der Verwendung von chrome: // downloads / gegoogelt und leider kann ich keinen Link zur Quelle bereitstellen, da diese nicht kitschig erhalten wurde. Die tatsächliche Implementierung der Klasse zum Abrufen des Dateinamens ist unten angegeben.

Klasse, um den Namen der heruntergeladenen Datei über Chrome zu erhalten: // downloads /
	private static final long DOWNLOADS_PAGE_LOAD_TIMEOUT = 5_000;
	private static final long MAX_GET_FILE_NAME_ATTEMPT = 5;
 
	public static String getLastDownloadedFilename() throws DownloaderException {
        String[] filename = new String[1];
        Exception[] ex = new Exception[1];
        WebDriver driver = WebDriverRunner.getWebDriver();
        JavascriptExecutor executor = (JavascriptExecutor) driver;
        Utils.driver.openNewTabCheckAndClose(
                () -> {
                    executor.executeScript("window.open('','_blank');");
                },
                () -> {
                    driver.get("chrome://downloads/");
 
                    for (int i = 0; i < MAX_GET_FILE_NAME_ATTEMPT; i++) {
                    	ex[0] = null;
                        sleep();
                    	try {
                        	WebElement element = (WebElement) executor.executeScript(
                                    "return document.querySelector('downloads-manager').shadowRoot.querySelector('downloads-item').shadowRoot.getElementById('file-link')");
                        	filename[0] = element.getText();
                            LOGGER.info("Attempt get file name " + i + ". Name = '" + filename[0] + "'");
                    	} catch (WebDriverException e) {
                        	ex[0] = e;
                            LOGGER.info("Failed attempt "+ i + " to get filename text: " + e.getMessage());
                        	continue;
                    	}
                    	if (filename[0] != null && !filename[0].isEmpty()) {
                        	 //             
                         	executor.executeScript(
                                    "document.querySelector('downloads-manager').shadowRoot.querySelector('downloads-item').shadowRoot.getElementById('remove').click()");
                        	break;
                    	}
                    }
                }
    	);
 
    	if (filename[0] != null && !filename[0].isEmpty()) {
            return filename[0];
    	}
 
    	String message = "Timeout. Can not get last downloaded file name from chrome://downloads/. File name is '" + filename[0] + "'. Exception: " + ex[0].getMessage();
        LOGGER.warning(message);
    	throw new DownloaderException(message, ex[0]);
	}

All Articles