File / Datei Download mit Selenium / WebDriver

27. Januar 2016 Softwaretest von Eric Kubenka

Das Problem

Oft stolpert man im Bereich der Testautomatisierung über das Herunterladen von Dateien und dem anschließenden Überprüfen Dieser. In den meisten Fällen dreht es sich dabei um diverse Bestätigungsdokumente, wie auch zuletzt bei mir, um Bestellbestätigungen im PDF-Format, welche die zuvor automatisiert eingetragenen Daten natürlich enthalten sollen/müssen.

Leider stellt Selenium / WebDriver dafür keine geeigneten Methoden bereit, da der Download Sache des Browser ist und in nativen Fenstern verwaltet wird, auf welche Selenium keinen Zugriff erhält.

Die meistgegebene Antwort

Die verbreiteste Antwort auf genau diese Frage im Netz schlägt vor, die Auto-Download-Einstellungen des zu Grunde liegenden Browser so zu konfigurieren, dass die Downloads an einer klar definierten Stelle automatisch beim Aufruf eines downloadbaren Dokuments abgelegt werden.

Schwachstelle: Ausführungsserver ungleich Seleniumhost

Doch diese Lösung ist nicht zufriedenstellend, vor allem dann nicht, wenn ein Selenium-Grid zur Ausführung verwendet wird oder, wie in meinem Fall, der Ausführungsserver des Skriptes nicht zeitgleich der Selenium-Host ist.

Vor allem aber, wird dadurch das ursprüngliche Problem, einen Dateidownload vernünftig zu automatisieren, nicht gelöst und mehr oder weniger elegant umgangen.

Lösung: DownloadHandler mittels Http-Request

Die Lösung des eigentlichen Problems liegt in einem DownloadHandler, welcher nach folgendem Prinzip arbeitet:

  1. Download-Target des WebElements ermitteln
  2. Cookies der aktuellen Selenium / WebDriver-Session speichern
  3. Http-Request gegen den Download-Target (1.) mit den extrahierten Cookies (2.) feuern
  4. Die Http-Response entsprechend auf dem Ausführungsserver speichern
  5. Weiter: Die Datei in weiteren Schritten verarbeiten und ggf. den Inhalt prüfen
  6. NiceToHave: Heruntergeladene Dateien nach der Testdurchführung entfernen

Wichtig in diesen Schritten ist, dass die Cookies entsprechend beim Request übergeben werden, da sonst beispielweise Download-Links hinter einem Login nicht korrekt heruntergeladen werden können.

Code-Snippet

// set file to download
URL fileToDownload = new URL("http.code-fever.de");

// Set target file
File downloadedFile = new File(System.getProperty("java.io.tmpdir") + "\\" + "targetFileName.html");

// Open connection
URLConnection request = fileToDownload.openConnection();

// Set cookies
if (this.isImitateCookies()) {
    request.setRequestProperty("Cookie", this.getImitatedCookies(driver));
}

// Buffer / Download
InputStream in = request.getInputStream();
FileOutputStream out = new FileOutputStream(downloadedFile);
byte[] buffer = new byte[1024];
int len = in.read(buffer);
while (len != -1) {
    out.write(buffer, 0, len);
    len = in.read(buffer);
    if (Thread.interrupted()) {
        throw new InterruptedException();
    }
}
in.close();
out.close();

// Return download Path...
final String absoluteFilePath = downloadedFile.getAbsolutePath();

Und damit ist auch bereits alles erledigt. Die vollständige Klasse gibt es hier auf GitHub - FileDownloader.

Das gesamte Maven-Projekt mit einem simplen Test und weiteren Funktionen im FileDownloader habe ich auf GitHub bereitgestellt.

HappyTesting

Zurück