Comment nous avons testé le glisser-déposer en HTML5

D'une manière ou d'une autre, tout le monde a été confronté à des situations où quelque chose d'inhabituel s'est produit dans un cadre banal. Un cas similaire nous est arrivé lors du test d'une nouvelle application dans un environnement cent fois testé. Une surprise pour nous a été l'utilisation de certaines fonctionnalités HTML5 dans le front-end, ou plutôt, l'impossibilité d'automatiser le test des opérations de glisser-déposer à l'aide des outils Selenium WebDriver standard. Nous voulons parler de cette expérience.



Imaginez un projet technologiquement très similaire au précédent (à notre avis, il a eu un petit effet négatif en termes de compréhension et d'analyse du problème qui est apparu), mais la version d'Angular entre les projets est passée de 1.x à 5.x et la bibliothèque Selenide pour les autotests UI a été ajoutée .

L'application Web développée avait une page avec un certain ensemble d'entités qui pouvaient être déplacées entre elles. Imaginez notre surprise lorsqu'une tentative d'effectuer un auto-test de vérification des fonctions de glisser-déposer à l'aide des outils Selenide a échoué. Il semblerait que ce qui aurait pu mal tourner? Sur le projet précédent, sur un environnement de test similaire, tout fonctionnait parfaitement.

Tout d'abord, nous avons vérifié la fonction glisser-déposer des fonctions Séléniure et Sélénium dans le navigateur actuel en utilisant un exemple d'une autre application Web. Tout fonctionne. Versions mises à jour, on ne sait jamais ...
Nous avons décidé de vérifier si nous traînons et là. Et faire le mauvais choix d'éléments lors de l'utilisation d'Angular est assez facile. Nous nous sommes assis avec un développeur frontal et avons compris que les éléments de glisser-déposer étaient correctement sélectionnés.

En général, l'environnement de test fonctionne, les méthodes de test sont écrites correctement, le glisser-déposer fonctionne à la main, mais l'autotest ne fonctionne pas. Et il n'y a aucune raison à cela à première vue.

Enfin, nous avons supporté le fait du problème et sommes allés chercher une solution sur Internet. Quelle a été notre surprise lorsque nous avons trouvé le problème ouvert Chrome WebDriver # 3604 du 03/04/2016 . Pensez-y, depuis le printemps 2016, officiellement, il y a un problème de glisser-déposer cassé dans Chrome WebDriver, sans parler des autres navigateurs. Non, cela fonctionne certainement, mais pas lors de l'utilisation de HTML5. Et comme il s'est avéré dans le processus d'analyse du problème, notre application a utilisé l'implémentation glisser-déposer en utilisant HTML5.

Quelles sont les implémentations glisser-déposer pour les tests en HTML5? Sur Internet, deux solutions ont été trouvées:

  • Utilisez la bibliothèque Java awt.Robot (ou un clicker tiers);
  • Utilisez javascript.

Nous avons probablement gagné un peu d'argent ou enterré dans le problème, mais tout de suite je ferai une réservation que la première solution choisie ne nous convenait pas :)

Que dire de l'implémentation sur Robot:

  • Nous interceptons la souris, émulant des actions utilisateur complètes;
  • Nous utilisons le sélénium pour déterminer les coordonnées des éléments;
  • Étant donné que des éléments en sélénium sont utilisés, vous n'avez pas besoin de modifier les localisateurs. Nous essayons sur le projet d'utiliser xpath;
  • Il est écrit en Java, la syntaxe est intuitive, bonne documentation.

Mais quelque chose à propos de l'implémentation JavaScript m'est venu à l'esprit:

  • Tout se passe sur JavaScript à l'intérieur du navigateur (les actions sont cachées aux yeux du testeur et ces actions interfèrent avec le code);
  • Parmi les bibliothèques js pour tester le glisser-déposer sur Internet, une a été trouvée, dont la source n'était pas si facile à trouver;
  • La bibliothèque trouvée devra être terminée avec un fichier adapté à vos besoins, car elle implémente uniquement un glisser-déposer propre. Et nous, par exemple, nous avions besoin de faire glisser -> déplacer -> maintenir -> déposer;
  • La bibliothèque est implémentée comme un module complémentaire jQuery, et il sera donc nécessaire de comprendre la structure jQuery;
  • Nous devrons convertir les localisateurs en CSS (jquery ne fonctionne pas avec xpath);
  • Il est impossible d'utiliser la recherche d'éléments Sélénium, vous devrez coller les localisateurs avec des «stylos».

À première vue, la première solution était beaucoup plus pratique et a été testée.

//Setup robot Robot robot = new Robot(); robot.setAutoDelay(50); //Fullscreen page so selenium coordinates work robot.keyPress(KeyEvent.VK_F11); Thread.sleep(2000); //Get size of elements Dimension fromSize = dragFrom.getSize(); Dimension toSize = dragTo.getSize(); //Get centre distance int xCentreFrom = fromSize.width / 2; int yCentreFrom = fromSize.height / 2; int xCentreTo = toSize.width / 2; int yCentreTo = toSize.height / 2; //Get x and y of WebElement to drag to Point toLocation = dragTo.getLocation(); Point fromLocation = dragFrom.getLocation(); //Make Mouse coordinate centre of element toLocation.x += xOffset + xCentreTo; toLocation.y += yCentreTo; fromLocation.x += xCentreFrom; fromLocation.y += yCentreFrom; //Move mouse to drag from location robot.mouseMove(fromLocation.x, fromLocation.y); //Click and drag robot.mousePress(InputEvent.BUTTON1_MASK); //Move to final position robot.mouseMove(toLocation.x, toLocation.y); //Drop robot.mouseRelease(InputEvent.BUTTON1_MASK); 

En général, la solution fonctionne ... Cependant, au cours de son développement, ses problèmes sont devenus clairs.

  • Le mouvement de la souris ou la minimisation du navigateur lors de l'exécution des tests entraine des interférences au cours des tests et leur chute;
  • Impossible d'exécuter des tests en parallèle à l'aide de JUnit / TestNG. À moins de paralléliser via des tâches distinctes dans CI.
  • Impossible de contrôler la souris sur la machine distante via Selenium Grid / Selenoid;
  • En cas de panne du navigateur, Robot peut facilement cliquer / faire glisser quelque chose sur le bureau ou dans une autre application ouverte.

Au final, cependant, l'implémentation JavaScript ...

Je voudrais dire tout de suite que nous avons réussi à résoudre le problème de l'utilisation des localisateurs xpath en utilisant le plugin jQuery jquery.xpath.js.

Et la bibliothèque drag_and_drop_helper.js (source ici ) est devenue l'outil principal pour js contrôler les opérations de glisser-déposer. Cela n'a aucun sens de trier son travail, mais de savoir comment nous y avons travaillé un peu plus tard.

Maintenant directement sur l'implémentation dans les tests. Chez Selenide, tout est simple. Avant d'utiliser le glisser-déposer, vous devez charger les bibliothèques JS utilisées:

 StringBuilder sb = new StringBuilder(); sb.append(readFile("jquery-3.3.1.min.js")); sb.append(readFile("jquery.xpath.min.js")); sb.append(readFile("drag_and_drop_helper.js")); executeJavaScript(sb.toString()); 

Naturellement, jQuery doit être chargé s'il n'est pas déjà dans l'application.

Dans la version originale de la bibliothèque, il suffit d'écrire ce qui suit:

 executeJavaScript("$('" + source + "') .simulateDragDrop({ dropTarget: '" + target + "'});"); 

source et cible sont des localisateurs css d'éléments glisser-déposer.

Comme indiqué ci-dessus, nous utilisons souvent des localisateurs xpath dans le projet, donc après un peu de raffinement, la bibliothèque a commencé à les accepter:

 executeJavaScript("$(document).xpath('" + source + "').simulateDragDrop({ dropTarget: '" + target + "'});"); 

Maintenant, en fait, sur la bibliothèque drag_and_drop_helper.js. Il y a des morceaux dans le bloc de code simulateEvent qui sont responsables de certains événements de souris. Il est inutile de répertorier les événements possibles des opérations de glisser-déposer dans HTML5; ces informations sont faciles à trouver.

Pour les tests, nous devions implémenter une fonction qui déplace l'élément et maintient la souris sur l'élément cible. Et cela, comme dans la bibliothèque source, n'est pas fourni.

Par analogie, nous avons ajouté l'événement dragenter à la bibliothèque (entre dragstart et drop).

 /*Simulating dragenter*/ type = 'dragenter'; var dragenterEvent = this.createEvent(type, {}); dragenterEvent.dataTransfer = event.dataTransfer; this.dispatchEvent($(options.dropTarget)[0], type, dragenterEvent); 

Mais cela ne suffit pas. Après tout, l'événement de mise en attente sera terminé instantanément. Mettre une pause fixe entre les événements dragEnter et drop ne semblait pas l'option la plus pratique. Après tout, au départ, on ne sait pas combien de temps l'application a besoin pour traiter un événement, le nombre et l'heure des vérifications dans les tests sont inconnus. Le délai entre ces événements devrait être au moins gérable. Au lieu de cela, nous avons décidé de diviser les tests de glisser-déposer en étapes et de ne pas émuler l'ensemble complet des événements de souris, c'est-à-dire d'ajouter la possibilité de gérer la liste des événements impliqués via le paramètre.

Et tout semble aller bien, de nouveaux défauts ne sont pas apparus, et certains des anciens ne le sont plus, et surtout, les tâches assignées sont en cours. Il semblerait que tout soit parfait. Cependant, les outils de développement modernes laissent le traitement de loin de deux événements et utilisent divers paramètres de l'élément déplacé. Supposons que nous ayons cette solution lors de l'exécution du glisser-déposer qui provoque des erreurs dragStartListener. Mais comme ça ne casse rien, nous nous n'avons pas commencé à changer autre chose. Cependant, dans une autre application, vous devrez probablement terminer ce moment.

Nous voulons résumer ce qui précède. Étonnamment, un fait! HTML5 est sorti en 2013, les navigateurs le prennent en charge depuis plusieurs années déjà, des applications ont été développées pour cela, mais webDriver, hélas, ne sait toujours pas comment utiliser ses capacités. Et le test des opérations de glisser-déposer doit être implémenté avec des outils tiers, compliquer l'architecture et passer à toutes sortes d'astuces. Oui, il existe de tels outils et «danser avec un tambourin» ne fait que nous rendre plus forts, mais je veux toujours avoir une solution de travail prête à l'emploi.

D'après notre expérience, nous pouvons dire que de tels problèmes ne sont pas si courants aujourd'hui, bien que le glisser-déposer soit utilisé partout. La question est probablement le choix des technologies de développement d'applications Web. Cependant, le pourcentage d'applications utilisant HTML5 augmente régulièrement, les frameworks se développent et il serait formidable que les développeurs de navigateurs et de pilotes pour eux ne soient pas en reste.

PS Et enfin, un peu de paroles. Je voudrais conseiller à tout le monde, si possible, de ne pas prendre en compte la banalité de la situation ou la proximité de l'environnement de test avec une sorte de modèle lors de l'analyse des problèmes. Cela peut conduire à des conclusions incorrectes ou à une perte de temps.

Source: https://habr.com/ru/post/fr437200/


All Articles