Mise en œuvre du processus de téléchargement d'un fichier depuis un conteneur avec un navigateur vers un framework de test

Automatisation des tests End-2-End d'un système d'information intégré
Partie 2-2. Implémentation du processus de téléchargement d'un fichier depuis un conteneur avec un navigateur vers un framework de test. Recherchez le nom du fichier téléchargé par le navigateur


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


Lorsque nous développions des autotests End-2-End pour l'interface utilisateur, nous étions confrontés à la question «Comment obtenir le nom du dernier chargé navigateur de fichiers de WebDriver? ", Google n’a rien obtenu rapidement. Par conséquent, j'ai écrit cet article, qui a en même temps dit ce que nous avions exactement un problème et comment nous l'avons résolu.

Avec cet article, nous continuons une série de publications sur la façon dont nous avons automatisé le processus de test manuel (ci-après dénommé auto-tests) d'un grand système d'information (ci-après dénommé Systèmes) dans l'un des principaux projets LANIT et ce qui en est ressorti.

image
la source


L'article lui-même complète le cycle, ci-dessous est un lien vers toutes les parties précédentes:
Partie 1. Organisationnelle et managériale. Pourquoi avions-nous besoin d'automatisation. Organisation du processus de développement et de gestion. Organisation de l'utilisation
Partie 2. Technique. Architecture et pile technique. DĂ©tails de mise en Ĺ“uvre et surprises techniques
Partie 2-1. Implémentation de la classe de base pour tous les tests et JUnit RuleChain.

C'était il y a un an. Aujourd'hui, cela n'est peut-être pas pertinent. Écrivez dans les commentaires si vous savez comment traiter efficacement des fichiers avec plusieurs serveurs de grille sélénoïde.

Lors du développement des «autotests», nous avons eu la tâche de télécharger (télécharger) des fichiers à partir du système avec une analyse ultérieure de leur contenu. Pour «télécharger» des fichiers à partir du système testé, nous utilisons les solutions suivantes:
  • pour le mode de lancement "local" (lancement directement sur le PC de travail) - lorsque le navigateur "local" est initialisĂ©, le nom du dossier local temporaire lui est transmis en paramètre. Ensuite, le fichier est lu directement Ă  partir du dossier local pour une analyse ultĂ©rieure;
  • pour le mode "Ă  distance" (via Bamboo) - le fichier a Ă©tĂ© "extrait" du conteneur avec le navigateur via la fonction de serveur Solenoid: selenoid-host.example.com : 4444 / download / {SESSION_ID} / {FILE_NAME}


Les détails sont décrits dans la documentation.

Pour les deux modes, pour accéder au fichier, il fallait connaître son nom. Ce fut une surprise. Le problème du manque de données sur le nom du fichier «download» était le suivant:
  • après avoir «cliqué» sur le bouton «tĂ©lĂ©charger le fichier», le navigateur a tĂ©lĂ©chargĂ© le fichier dans le dossier local appropriĂ© dans le conteneur;
  • dans ce cas, le nom du fichier a Ă©tĂ© formĂ© dynamiquement et, comment le dĂ©terminer Ă  l'avance, nous n'avons pas pu le trouver. C'Ă©tait une caractĂ©ristique de notre système de test;
  • En outre, ce fichier doit ĂŞtre «retiré» du conteneur et une vĂ©rification commerciale de son contenu doit ĂŞtre effectuĂ©e;
  • pour «extraire» le fichier, vous devez connaĂ®tre son nom, mais nous ne connaissions pas le nom, car le nom Ă©tait gĂ©nĂ©rĂ© dynamiquement et il n'y avait aucune valeur dans le lien.


De plus, la situation était aggravée par le fait qu'en raison de la grande complexité de certains tests, plusieurs fichiers pouvaient être déchargés pendant le test dans le cadre de différents scripts de test indépendants de la composition du test lui-même.
La meilleure solution pour nous était la méthode selon laquelle nous avons déterminé le dernier fichier téléchargé. Il y avait plusieurs façons de procéder:
  • . . , ;
  • Google Chrome javascript chrome://downloads/, html-. .




L'analyse de la composition des fichiers chargés par le navigateur pour le mode local est une tâche triviale.
Pour le mode distant, vous devez utiliser la fonction «non documenté» du serveur selenoid: selenoid-host.example.com : 4444 / download / {SESSION_ID} affiche une liste de tous les fichiers téléchargés avec succès, où SESSION_ID est un ID de session selenoid.
En général, le schéma fonctionne bien à une exception près: nous Vous devez attendre un certain temps jusqu'à ce que le fichier soit téléchargé et apparaisse dans la liste. L'attente peut être définie via un cycle de temporisation, cependant, de cette façon, nous ne pouvons pas obtenir d'informations sur une éventuelle erreur de téléchargement de fichier. Nous pouvons seulement déterminer que le fichier n'a pas été chargé dans ce circuit. Par conséquent, à la fin, nous avons opté pour la méthode de détermination du nom de fichier via la page chrome: // Downloads /.

Obtenir le nom du fichier via le chrome: // téléchargements / page


Cette méthode fonctionne aussi bien en mode local que distant. Le schéma de travail est assez simple:
  • exĂ©cutez le script java pour ouvrir la fenĂŞtre chrome: // tĂ©lĂ©chargements /;
  • traiter les donnĂ©es dans la fenĂŞtre de la manière habituelle. Attendez que le premier fichier de la liste soit chargĂ© et dĂ©terminez son nom;
  • fermez la fenĂŞtre chrome: // Downloads / et retournez le nom du fichier que vous recherchez.


Nous avons recherché sur Google l’idée d’utiliser chrome: // Downloads / et, à mon grand regret, je ne peux pas fournir de lien vers la source, car elle n’était pas conservée. L'implémentation réelle de la classe pour obtenir le nom de fichier est donnée ci-dessous.

Classe pour obtenir le nom du fichier téléchargé via chrome: // téléchargements /
	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