Conseils de test suralimentés pour 2019 : un didacticiel de test d'automatisation Java

Publié: 2022-03-11

Chaque année, des ingénieurs en automatisation des tests du monde entier recherchent les derniers outils et techniques afin de rendre leur cadre d'automatisation des tests plus stable, plus rapide et plus facile à utiliser et à entretenir. Ceci est essentiel pour assurer la poursuite de l'adoption généralisée de leur cadre au sein de leur entreprise. En général, les cadres gonflés et obsolètes tombent rapidement en désuétude.

Dans cet article, nous examinerons certaines des façons dont vous pouvez mettre à jour votre cadre pour 2019 et comment vous préparer pour 2020. Afin d'améliorer mon cadre, je me concentre toujours sur les « points douloureux ». Ce sont les domaines qui sont complexes à mettre en place ou causent le plus de pannes. J'ai identifié trois domaines principaux que je souhaitais simplifier ou améliorer :

  1. Grille de sélénium
  2. Attend
  3. Outils de développement Chrome

Selenium Grid est notoirement difficile à configurer et peut échouer sans avertissement. Je voulais voir ce qui, le cas échéant, s'était amélioré ici. Je voulais également vérifier si de nouvelles waits avaient été ajoutées à l'API Selenium pour améliorer la stabilité de tous les tests que j'avais créés. Enfin, je voulais voir si je pouvais commencer à interagir avec Chrome DevTools via Selenium, qui est devenu un élément essentiel de la boîte à outils de tout testeur.

Conseil n° 1 : dockerisez votre grille de sélénium

Selenium Grid est notoirement difficile à configurer, instable et difficile à déployer ou à contrôler en version sur un pipeline CI. Un moyen beaucoup plus simple, stable et maintenable consiste à utiliser les images Selenium Docker pré-construites.

Remarque : le seul inconvénient de cette méthode est qu'IE (Internet Explorer) n'est pas pris en charge, car il n'est pas encore possible de conteneuriser le système d'exploitation Windows.

Mise en place

Pour être opérationnel, vous devez d'abord installer Docker et Docker Compose sur votre machine. Si vous utilisez Windows 10 ou un Mac, ils seront tous deux installés via Docker Desktop.

Démarrage de votre grille

Le référentiel Selenium officiel sur Docker Hub contient des images Docker prédéfinies pour votre hub Selenium et vos nœuds Firefox et Chrome.

Le moyen le plus simple de les utiliser dans une grille Selenium locale consiste à créer un fichier Docker Compose dans le répertoire racine de votre projet. Nommez le fichier docker-compose.yml pour simplifier les choses.

J'ai inclus un exemple ci-dessous qui crée la grille suivante :

  • Un seul concentrateur de sélénium
  • Un nœud Chrome
  • Un nœud Firefox
 #docker-compose.yml version: "3" services: selenium-hub: image: selenium/hub:3.141.59-neon container_name: selenium-hub ports: - "4444:4444" chrome: image: selenium/node-chrome:3.141.59-neon volumes: - /dev/shm:/dev/shm depends_on: - selenium-hub environment: - HUB_HOST=selenium-hub - HUB_PORT=4444 firefox: image: selenium/node-firefox:3.141.59-neon volumes: - /dev/shm:/dev/shm depends_on: - selenium-hub environment: - HUB_HOST=selenium-hub - HUB_PORT=4444

Le fichier Docker Compose décrit la configuration de votre Grid. Pour plus d'informations sur la création de fichiers Docker Compose, veuillez consulter la documentation officielle.

Pour démarrer votre Grid, utilisez simplement n'importe quelle fenêtre de terminal (une fenêtre powershell ou cmd sous Windows) pour exécuter la commande suivante depuis le répertoire racine de votre projet :

 docker-compose up

Connexion au réseau

Vous pouvez vous connecter à votre Selenium Grid exactement de la même manière que vous le faites normalement, car le Hub écoute sur le port 4444 de votre machine locale. Voici un exemple où nous configurons notre pilote pour utiliser notre Chrome Node.

 // Driver.java protected static RemoteWebDriver browser; DesiredCapabilities cap = new DesiredCapabilities(); ChromeOptions chromeOptions = new ChromeOptions(); cap.setCapability(ChromeOptions.CAPABILITY, chromeOptions); cap.setBrowserName("chrome"); driver = new RemoteWebDriver(cap);

Vous pouvez ensuite utiliser la bibliothèque TestNG pour exécuter vos tests sur plusieurs nœuds en parallèle comme d'habitude.

Il convient de noter qu'il est possible d'avoir plusieurs navigateurs en cours d'exécution sur chaque nœud. Cependant, cela est déconseillé et l'utilisation d'un navigateur par nœud est considérée comme la meilleure pratique pour des performances optimales.

Trucs et astuces supplémentaires

Si vous voulez voir ce qui se passe sur le navigateur afin de pouvoir déboguer vos tests, il vaut la peine d'avoir une version de debug de votre fichier docker-compose.yml qui télécharge les nœuds de debug du navigateur. Ceux-ci contiennent un serveur VNC afin que vous puissiez regarder le navigateur pendant que le test s'exécute.

Il est également possible d'exécuter les navigateurs sans tête pour une vitesse accrue (la manière habituelle) et Selenium fournit également des versions de base des images afin que vous puissiez créer vos propres images si vous avez besoin d'installer un logiciel supplémentaire.

Pour créer une version stable du Grid pour votre pipeline CI, il est également possible de déployer votre Grid sur Kubernetes ou Swarm. Cela garantit que tous les Dockers sont rapidement restaurés ou remplacés en cas de défaillance.

Conseil n° 2 : Attentes intelligentes

Comme tout ingénieur en automatisation des tests le sait, les temps d' waits sont cruciaux pour la stabilité de votre infrastructure d'automatisation des tests. Ils peuvent également accélérer votre test en rendant les sleeps en veille ou les pauses redondantes et en surmontant les problèmes de réseau lent et de navigateurs croisés. Vous trouverez ci-dessous quelques conseils pour rendre vos waits encore plus résilientes.

Tutoriel de test d'automatisation Java #2 : Opérateurs logiques dans les attentes : Soyez précis avec vos attentes

La classe ExpectedConditions s'est développée au fil du temps et englobe maintenant presque toutes les situations imaginables. Alors que ExpectedConditions.presenceOfElementLocated(locator) est souvent suffisant, il est recommandé d'utiliser les méthodes de la classe ExpectedCondition pour couvrir chaque action de l'utilisateur en les incorporant dans votre classe Actions.java . Cela protégera vos tests contre la plupart des problèmes de navigateurs croisés ou de sites Web lents.

Par exemple , si cliquer sur un lien entraîne l'ouverture d'un nouvel onglet, utilisez ExpectedConditions.numberOfWindowsToBe(2) . Cela garantira que l'onglet est là avant d'essayer d'y basculer.

Vous pouvez également utiliser une wait pour vous assurer que vous capturez tous les éléments présents sur la page lors de l'utilisation findElements . Cela peut être particulièrement utile si une page de search met du temps à renvoyer ses résultats. Par exemple, cette ligne :

 List<WebElement> results = driver.findElements(locators.RESULTS);

Il peut en résulter un tableau List vide si vos résultats de recherche n'ont pas encore été chargés. Au lieu de cela, il est préférable d'utiliser la condition attendue numberOfElementsToBeMoreThan pour attendre que les résultats soient supérieurs à zéro. Par exemple:

 WebElement searchButton = driver.findElement(locators.SEARCH_BUTTON); searchButton.click(); new WebDriverWait(driver, 30) .until(ExpectedConditions .numberOfElementsToBeMoreThan(locators.RESULTS, 0)); List<WebElement> results = driver.findElements(locators.RESULTS); results.get(0).click();

Désormais, votre commande findElements ne s'exécutera qu'après le retour des résultats de la recherche.

Cette wait est également utile pour trouver un élément unique lorsque vous avez affaire à un frontal qui ne fonctionne pas bien avec Selenium (par exemple, les sites Web angulaires). Créer une méthode comme celle-ci protégera vos tests, les rendant beaucoup plus stables.

 protected static WebElement waitForElement(By locator){ try { new WebDriverWait(browser, 30) .until(ExpectedConditions .numberOfElementsToBeMoreThan(locator, 0)); } catch (TimeoutException e){ e.printStackTrace(); Assert.fail("Timeout: The element couldn't be found in " + WAIT + " seconds!"); } catch (Exception e){ e.printStackTrace(); Assert.fail("Something went wrong!"); } return browser.findElement(locator); }

Il est même possible d'attendre que des éléments ne soient plus visibles. Ceci est particulièrement utile si vous attendez qu'une fenêtre contextuelle disparaisse après avoir cliqué sur le bouton OK ou Save avant de poursuivre votre test.

 WebElement okButton = driver.findElement(locators.OK_BUTTON); okButton.click(); new WebDriverWait(driver, 30) .until( ExpectedConditions .invisibilityOfElementLocated(locators.POPUP_TITLE) );

Toutes les méthodes décrites ci-dessus et bien d'autres sont répertoriées dans la documentation officielle. Cela vaut la peine de passer dix minutes à parcourir toutes les possibilités et à améliorer la stabilité de votre framework.

Tutoriel n° 2 sur les tests d'automatisation Java : Opérateurs logiques dans les attentes

Un bon moyen de renforcer la résilience de vos waits consiste à utiliser des opérateurs logiques. Par exemple, si vous vouliez vérifier qu'un élément a été localisé ET qu'il est cliquable, vous utiliseriez le code suivant (attention, ces exemples renvoient une valeur booléenne) :

 wait.until(ExpectedConditions.and( ExpectedConditions.presenceOfElementLocated(locator), ExpectedConditions.elementToBeClickable(locator) ) );

L'opérateur OU serait approprié si vous n'étiez pas sûr que le titre de la page puisse changer ou non. Ensuite, vous pouvez inclure une vérification de l'URL si la première condition échoue, pour confirmer que vous êtes définitivement sur la bonne page.

 wait.until(ExpectedConditions.or( ExpectedConditions.titleIs(expectedTitle), ExpectedConditions.urlToBe(expectedUrl) ) );

Ou si vous vouliez vous assurer qu'une case à cocher n'est plus activée après qu'une action est effectuée sur la page, alors l'opérateur NOT est approprié.

 wait.until(ExpectedConditions.not( ExpectedConditions.elementToBeClickable(locator) ) );

L'utilisation d'opérateurs peut rendre vos waits plus résilientes et aboutir à des tests moins fragiles.

Conseil n° 3 : Chrome DevTools : simulation des conditions du réseau

L'exécution de votre application Web sur localhost ou sur un réseau local peut donner une fausse impression quant à ses performances lorsqu'elle est exécutée dans la nature. La possibilité de limiter diverses vitesses de chargement et de téléchargement vous donnera une meilleure représentation de la façon dont votre application fonctionnera sur Internet, où les délais d'attente peuvent entraîner l'échec des actions. Nous pouvons commencer à simuler cela en utilisant la puissance des DevTools de Chrome.

Le code suivant ouvrira la page d'accueil de Toptal en utilisant différentes vitesses de téléchargement et de téléchargement. Tout d'abord, nous allons stocker nos vitesses dans un fournisseur de données TestNG en utilisant le code suivant :

 import org.testng.annotations.DataProvider; public class ExcelDataProvider { @DataProvider(name = "networkConditions") public static Object[][] networkConditions() throws Exception { return new Object[][] { // Upload Speed, Dowload Speed in kb/s and latency in ms. { 5000 , 5000, 5 }, { 10000, 7000, 5 }, { 15000, 9000, 5 }, { 20000, 10000, 5 }, { 0, 0 }, }; } }

Remarque : La limitation de chargement et de téléchargement est en kb/s et la latence est en ms .

Ensuite, nous pouvons utiliser ces données pour exécuter notre test dans différentes conditions de réseau. Dans le cadre du test, le CommandExecutor exécutera la commande dans la session actuelle du navigateur. Cela activera à son tour les paramètres nécessaires dans la fonctionnalité des outils de développement de Chrome pour simuler notre réseau lent. Le code dans l'instruction if peut être inclus dans une méthode @BeforeClass lors de l'exécution d'une suite de tests.

 import org.testng.annotations.Test; import com.google.common.collect.ImmutableMap; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.openqa.selenium.remote.Command; import org.openqa.selenium.remote.CommandExecutor; import org.openqa.selenium.remote.Response; public class TestClass { // load our data provider @Test(dataProvider = "networkConditions") public void test(int download, int upload, int latency) throws IOException { // only run if the network is throttled if (download > 0 && upload > 0) { CommandExecutor executor = driver.getCommandExecutor(); // create a hashmap of the required network conditions Map map = new HashMap(); // you can even test 'offline' behaviour map.put("offline", false); map.put("latency", latency); map.put("download_throughput", downloadThroughput); map.put("upload_throughput", uploadThroughput); // execute our code Response response = executor.execute( new Command(driver.getSessionId(), "setNetworkConditions", ImmutableMap.of("network_conditions", ImmutableMap.copyOf(map)))); } // Open the website driver.get("https://www.toptal.com/"); // You can then check that elements are loaded etc. // Don't forget to use waits! } }
En relation : Construire en toute confiance : un guide des tests JUnit

Astuce bonus : comment gérer vos cookies

Les cookies du navigateur peuvent entraîner différents comportements dans votre application, selon qu'ils ont été enregistrés ou non lors d'une session précédente (par exemple, l'application peut se charger avec un utilisateur déjà connecté). Il est recommandé d'effacer vos cookies avant chaque test pour vous assurer qu'ils ne causent pas de problèmes.

Le code ci-dessous vous permet de supprimer tous vos cookies :

 driver.manage().deleteAllCookies();

Vous pouvez également supprimer un cookie par son nom :

 driver.manage().deleteCookieNamed("CookieName");

Ou obtenir le contenu d'un cookie :

 String myCookie = driver.manage().getCookieNamed("CookieName").getValue();

Ou obtenez tous les cookies :

 List<Cookie> cookies = driver.manage().getCookies();

Automatisation des tests en 2020 : regard vers l'avenir

Selenium 4 sortira au cours des prochains mois. Il est encore en cours de développement, mais comme une version alpha est déjà sortie, il vaut la peine de jeter un coup d'œil aux améliorations qu'il offrira.

Remarque : Vous pouvez suivre leur progression en consultant la feuille de route.

Standardisation W3C WebDriver

Selenium n'aura plus besoin de communiquer avec le navigateur via le protocole filaire JSON ; au lieu de cela, les tests automatisés communiqueront directement avec le navigateur. Cela devrait répondre à la fameuse nature floconneuse des tests Selenium, y compris la protection contre les mises à jour du navigateur. Espérons que la vitesse de test augmentera également.

Une grille de sélénium plus simple

La grille Selenium sera plus stable et plus facile à configurer et à gérer dans Selenium 4. Les utilisateurs n'auront plus besoin de configurer et de démarrer les hubs et les nœuds séparément car la grille agira comme un nœud et un hub combinés. De plus, Docker sera mieux pris en charge, les tests parallèles seront inclus de manière native et fourniront une interface utilisateur plus informative. Le suivi des requêtes avec Hooks vous aidera également à déboguer votre grille.

Documentation

La documentation de Selenium fera l'objet d'une refonte indispensable, n'ayant pas été mise à jour depuis la sortie de Selenium 2.0.

Modifications de l'API

La prise en charge des navigateurs Opera et PhantomJS sera supprimée. L'exécution sans tête peut être effectuée avec Chrome ou Firefox, et Opera est construit sur Chromium et, par conséquent, les tests de Chromium sont considérés comme suffisants pour ce navigateur.

WebElement.getSize() et WebElement.getLocation() sont désormais remplacés par une seule méthode WebElement.getRect() . Cependant, comme ceux-ci sont souvent utilisés pour créer des captures d'écran d'un seul élément, sachez qu'il y aura également une commande API pour capturer une capture d'écran d'un élément dans Selenium 4.

Pour WebDriver Window , les méthodes getPosition et getSize seront remplacées par la méthode getRect et les méthodes setPosition et setSize seront remplacées par la méthode setRect . Les méthodes fullscreen et minimize seront disponibles, afin que ces actions puissent être effectuées dans votre test.

Autres changements notables :

  • La classe Options de chaque navigateur étendra désormais la classe Capabilities .
  • Une driver.switchTo().parentFrame() a été ajoutée pour faciliter la navigation dans les cadres.
  • de nice localisateurs seront inclus qui fonctionnent à un niveau supérieur aux actuels. Ils seront une sous-classe de By .
  • Il y aura une implémentation de l'API DevTools , permettant aux utilisateurs de profiter des fonctionnalités offertes en utilisant le protocole de débogage Chrome (et équivalents sur d'autres navigateurs). Ceux-ci inclus:
    • Captures d'écran pleine page (y compris les éléments hors écran).
    • Journaux de diffusion en continu.
    • En attente d'événements de mutation sur la page.
  • De nombreuses méthodes et classes obsolètes seront également supprimées.

Remarque : Vous pouvez obtenir une version Alpha de Selenium 4 à partir du référentiel Maven. Il est fortement recommandé de l'essayer avec votre framework actuel (idéalement sur une branche sandbox), afin d'être prêt pour le changement.

Conclusion

Dans cet article, j'ai couvert quelques domaines dans lesquels j'ai amélioré mon framework d'automatisation des tests. Il est désormais plus stable et utilisable qu'auparavant, ce qui aura un impact positif sur toutes les personnes impliquées dans le cycle de vie de la livraison de logiciels.

Apporter les changements que j'ai décrits ci-dessus est un bon début, cependant, je vous recommande fortement de revoir l'ensemble de votre cadre pour les "points faibles", car il peut y avoir des améliorations que vous pouvez apporter et que je n'ai pas couvertes. Par exemple, utilisez-vous WebDriver Manager pour gérer vos pilotes ou les mettez-vous toujours à jour manuellement ?

Je recommanderais également de fixer une date pour le faire au moins une fois par an, même si idéalement ce serait tous les six mois. Dans l'article, j'ai inclus les changements à venir dans Selenium 4.0. Veuillez consulter les versions alpha de Selenium par vous-même. Les changements seront spectaculaires et vous devrez être préparé. J'espère que vous avez trouvé cela utile. Si vous découvrez de nouvelles méthodes ou techniques en faisant un peu de nettoyage de printemps sur votre framework, partagez-les avec d'autres lecteurs de ce blog en les ajoutant à la section des commentaires ci-dessous.

De plus, si vous souhaitez découvrir les tests automatisés dans Selenium et savoir comment utiliser les modèles Page Object pour écrire des routines de test maintenables et réutilisables, consultez Automation in Selenium: Page Object Model and Page Factory .

En relation : Le langage Dart : lorsque Java et C# ne sont pas assez pointus