Selenium est un outil qui permet d’effectuer des tests fonctionnels web automatisés sur la plupart des navigateurs, plateformes et languages.
Cet article présente
Si vous êtes impatient vous pouvez aller directement à la vidéo du test Selenium ou au code du test.
Pour bien comprendre Selenium, et savoir ce que l’on peut lui demander il est nécessaire de prendre un cas d’usage fonctionnel non trivial qui utilise des composants riches.
Pour cela prenons l’application générée par Celerio que vous pouvez reproduire vous même en ligne et prenons un cas d’usage conséquent.
En tant qu’administrateur je souhaite modifier un compte existant, me déconnecter pour ensuite m’identifier avec, puis me déconnecter pour me réidentifier en tant qu’administrateur et remettre enfin le compte modifié dans l’état précédent.
Le chemin fonctionnel souhaité est donc le suivant:
Voici un screencast de ce cas d’usage réalisé “manuellement”.
Ce chemin fonctionnels correspond aux étapes unitaires suivantes
admin
dans le champ identifiantadmin
dans le champ mot de passehomer
dans le champ identifianthomer
dans la liste de completion proposéehomer
est affichéecnorris
comme identifiantkickass
comme mot de passegmail@chucknorris.com
comme emailParis
comme addresseDroits attribués
admin
comme nomROLE_ADMIN
ROLE_GOD
Documents attachés
sauver
deconnexion
etc.
La présentation est assez longue, mais notez que chaque élément de cette liste représente bien une action réalisée par l’utilisateur.
La liste complète des actions capturées par Selenium IDE est présenté ci-dessous
En l’état la capture de Selenium IDE n’est pas utilisable pour les raisons suivantes:
Plusieurs axes d’amélioration s’offrent à nous.
Nous pouvons ajouter du code pour supprimer les cookies
Nous pouvons refactorer le code pour extraire les actions métiers
Nous pouvons mettre en oeuvre le Page factory pattern qui permet à la fois d’apporter du typage et de résoudre en partie la dépendance forte au DOM.
Nous pouvons ajouter des tests en plus pour vérifier le résultat des actions par exemple
Pour s’affranchir du temps de rendu des pages et des modifications du DOM, il est nécessaire d’utiliser les mécanismes de réessais de Selenium de façon judicieuse. L’utilisation de Thread.sleep()
à tire larigot étant à proscrire.
Nous pouvons également appliquer l’ensemble des bonnes pratiques de développement pour améliorer le script original et ainsi le rendre propre et efficace.
L’objet WebElement est un objet de trop bas niveau, nous pouvons utiliser des helpers pour être plus efficace
La problématique liée à l’utilisation de helpers est que la liste de fonctionnalités qui prennent des WebElement
est très longue.
La complétion dans votre IDE favori ne pourra pas vous aider sur les opérations possibles pour un WebElement
et un contexte donné.
Il faudrait que le l’élément porte lui-même les actions qu’il peut réaliser. Ainsi un bouton ne serait pas webElement
, mais un un objet de class Button
où seule la méthode click()
serait disponible.
La recherche d’utilisateur présente à l’utilisateur les fonctionnalités suivantes:
Ces fonctionnalités sont les mêmes sur les autres entités manipulées par l’application.
Il faudrait qu’à l’image du code des composants qui produisent la page via le DOM, produire le code client qui les consomme via selenium.
Ceci dans le but d’arriver à une description des composants de la page:
Les composants Table
, EntityAction
, Messages
, OrderBy
, Autocomplete
, ManyBooleans
, ChooseEnum
, StringRange
doivent être écrits de façon indépendantes des tests.
Le composant EntityAction
n’est qu’un aggregat de boutons
Un bouton est lui-même définit comme suit
Nous pouvons désormais ajouter dans le test ce type d’action
Le composant OrderBy
est écrit en connaissant comme le composant serveur produit le DOM côté client. Nous pouvons alors créer les méthodes isUp()
, isDown()
, up()
, down()
Dans le test nous pouvons donc réaliser les actions et assertions suivantes:
La sélection de la civilité est interressante, voici le code
Cela permet d’avoir côté test unitaire de la completion avec le type de donnée adéquate.
La suite est de componentariser les autocomplete qui est un composant plus complexe, celui-ci fait appel à de nombreuses requêtes Xpath
Pour la page d’édition d’un compte nous reprenons la même recette pour arriver à ceci:
Vous l’aurez compris, une fois le code du composant produit, nous pouvons créer des tests totalement décorrolés de leur implémentations. Votre IDE pourra vous guider sur les actions possible sur chaque composant.
L’objet AccountSearch ne contient que des références de composants, leur instanciation est réalisé à la façon du Page Factory Pattern.
Sauf qu’ici, leur instanciation est récursive, une class annotée @Page
peut avoir des propriétés @Page
. Il est à noter que les propriétés déjà créées seront également wrappées.
Après ces pérégrinations techniques, il faut revenir au besoin client final, et savoir communiquer au métier ce que réalise le test.
Pour cela, nous avons ajouté des méthodes qui présentent visuellement les actions effecutées. L’ajout de l’annotation FollowVisually à la classe de test permet d’activer ces messages.
La notification en elle même est l’appel direct à un composant javascript déjà présent sur la page cliente.
Le highlight des composants cliqués est également présent.
Nous pouvons désormais présenter au client final le test, et pouvons améliorer les messages, itérer sur ce qui est à tester fonctionnellement, et réaliser en direct les nouveaux tests.
Le build continu lui exécute les tests sans effets visuels, ainsi ceux-ci se déroulent aussi vite que le rendu et la vitesse de processing des pages le permettent.
Il est possible de pouvoir écrire des tests fonctionnels clairs, typés et rapide avec Selenium.
Pour cela, il faut investir du temps sur la création de composants qui savent intéragir avec le DOM.
© 2005-2015 Jaxio | @jaxiosoft | Mentions légales