Comment choisir une stratégie de sélecteurs web (CSS/XPath) ?

blog-thumb

Introduction

Comme vous le savez les outils d’automatisation des tests UI comme Selenium , WebdriverIO , etc utilisent le même principe de fonctionnement et partagent les mêmes problématiques.

Tous les tests réalisés avec un outil webdriver sont principalement basés sur le contenu du DOM et utilisent les sélecteurs web pour interagir avec l’interface utilisateur via des drivers (chromedriver, geckodriver, etc.).

Cette réalité représente un vrai problème de dépendance entre les tests et la structure de l’interface utilisateur, un changement ainsi au niveau de l’UI implique une mise a jour a faire au niveau des tests.

Il est donc essentiel de choisir soigneusement la meilleure stratégie pour résister au changement de l’interface utilisateur afin :

  • de minimiser les coûts de maintenances
  • d’augmenter la fiabilité des tests basés sur l’UI
  • d’avoir un pipeline stable
  • de livrer les produits le plus rapidement possible.

Dans cet article je vais vous présenter les sélecteurs d’éléments web officiellement supportés par le W3C, évaluer leurs inconvénients et leurs avantages afin de vous aider à choisir la meilleure stratégie pour mener à bien votre projet d’automatisation d’UI.

Le problème

Sans trop entrer dans les détails techniques de chaque outil, framework ou api, le principe de fonctionnement simplifié est le suivant:

1. Sélection de l’élément web (bouton, lien, menu déroulant, etc.) 2. Interaction avec l’élément sélectionné (simple clique, saisie d’un texte, récupération de texte, etc.) 3. Vérification des résultats à travers des assertions

Souvent les tests échouent durant l’étape de sélection de l’élément web et vous perdrez donc le temps dans l’analyse des messages d’erreur de type:

  • Not found exception
  • An element could not be located on the page
  • Unable to locate element
  • NoSuchElementError
  • X exception

Après analyse des erreurs, vous vous rendez compte qu’une simple balise html div à été supprimée par les développeurs ou la valeur de l’ID à été mise à jour de: <input type="text" id="user" name="user"> a <input type="text" id="username" name="username">

Cette problématique se multiplie notamment si les automaticiens et les développeurs ne sont pas dans la même équipe et / ou sans réelle collaboration.

Sans surprise, les résultats sont les suivants :

  • Tests non fiables (Flaky Tests)
  • Coût de maintenance élevé
  • Pipeline de livraison lent
  • Perte de motivation

La solution

L’élément essentiel de la solution est la capacité d’identifier le bon sélecteur / sélecteur (locator).

Qu’est ce qu’un bon sélecteur ?

Indépendamment du débat sur Xpath vs CSS, un bon sélecteur possède les caractéristiques suivantes:

  • Unique
  • Descriptif
  • Faible probabilité de changement

Les différentes stratégies webdriver

Nous passons maintenant à l’analyse des différentes stratégies supportés par le W3C afin d’identifier la meilleure stratégie possible.

Petit rappel de la liste des des stratégies officielles du W3C:

  • CSS selector
  • Link text selector
  • Partial link text selector
  • Tag name
  • XPath selector

Pour garder le focus sur l’essentiel et afin d’éviter d’entrer dans les détails de chaque stratégie qui ne sont pas nécessairement utiles, les différentes stratégies seront classés en grandes catégories:

  • Une mauvaise stratégie: Link Text, Partial Link Text et Tag Name
  • Une bonne stratégie: CSS et Xpath
  • Une très bonne stratégie: ID et Class
  • Une excellente stratégie: Attributs HTML personnalisés data-* avec les sélecteurs CSS

Les sélecteurs Link Text, Partial Link Text, et Tag Name ont le même problème, c’est le manque de résistance au changement qui peut avoir une page ou un composant html durant le cycle de vie d’un projet et donc les flaky tests !

Voici un simple exemple pour mieux comprendre la problématique:

Supposons que nous avons le code HTML suivant:

<h1 class="heading">Welcome to the-internet</h1>
<h2>Available Examples</h2>
<ul>
  <li><a href="/upload">File Upload</a></li>
  <li><a href="/floating_menu">Floating Menu</a></li>
  <li><a href="/forgot_password">Reset Password</a></li>
</ul>

Maintenant pour automatiser notre scénario de test forgot_password, nous avons besoin de cliquer sur le lien /forgot_password, la solution la plus simple pour sélectionner l’élément web c’est d’utiliser la stratégie Link Text avec l’instruction selenium webdriver suivante await driver.findElement(By.linkText("Reset Password")).click() Bien, le test (click) devrait fonctionner !

Maintenant le développeur repasse sur le code HTML, il trouve que Reset Password n’est pas trop sémantique et il serait super bien de changer le texte Reset Password par Forgot Password, un simple changement qui ne coûte rien !

Suite à cette modification, nous avons donc le nouveau code html suivant:

<h1 class="heading">Welcome to the-internet</h1>
<h2>Available Examples</h2>
<ul>
  <li><a href="/upload">File Upload</a></li>
  <li><a href="/floating_menu">Floating Menu</a></li>
  <li><a href="/forgot_password">Forgot Password</a></li>
</ul>

Nous exécutons à nouveau le même test forgot_password pour vérifier si tout va bien !

Exécution des tests en cours …

Boom !

Le test ne passe plus!, Ona la fameuse exception NoSuchElementException.

Vous devez comprendre maintenant que cette stratégie n’est pas la meilleure façon de faire ce travail, une telle stratégie axée sur le contenu est sans doute une mauvaise stratégie !

Utilisez-les uniquement si vous avez un besoin spécifique et qu’aucune autre option n’est disponible !

Bonne: CSS et Xpath

Indépendamment du débat sur Xpath vs CSS, ces deux sélecteurs sont conceptuellement très similaires, c’est pour cela je les ai rassemblés pour cette catégorie.

XPath dispose la possibilité de sélectionner des éléments parents, cette option est particulièrement intéressante pour certains scénarios et CSS dispose une syntaxe relativement simple !

Quelques points d’attention:

  • Ces types de sélecteurs avec des combinaisons de nom de balise, d’éléments descendants, de classe CSS (ou d’attribut d’élément) rendent le modèle de sélection strict ou lâche, ce qui signifie que de petites modifications HTML l’invalideront et perdront le sens qu’il pourrait correspondre à plus d’un élément HTML.

  • Lors de l’écriture d’un sélecteur Xpath ou CSS, il s’agit de trouver l’équilibre entre strict et lâche

  • Suffisamment stable et durable pour résister au changement HTML

  • Suffisamment strict pour échouer lorsque l’application échoue.

  • XPath ne fonctionne pas correctement dans Internet Explorer.

  • Les sélecteurs XPath absolus ne sont pas bons.

Très bonne: ID et Class

L’ID est la stratégie de sélection la plus sûre et doit toujours être votre premier choix. Selon les normes du W3C, l’ID est sensé d’être unique dans la page (by design), il est également indépendant du type et de l’emplacement de l’élément web. Les navigateurs possèdent également des méthodes efficaces pour récupérer un objet sur une page en utilisant leurs identifiants.

Comme l’ID, l’utilisation de l’attribut Class a l’avantage d’être moins impacté par les changements structurels de la page web et donc plus stable.

Lorsque vous utilisez les deux stratégies ID et Class, vous cibler directement des éléments spécifiques au lieu de vous fier à la structure de la page.

Bien évidemment si le développeur modifier un ID ou un l’attribut Class qui est déjà utilisé dans le framework de tests UI automatisés cela aura un impact sur vos scénario de test tests. Comme je l’ai toujours dit, l’automatisation commence par la communication, discuter avec les développeurs c’est toujours important et nécessaire.

Excellente: Attributs data-* avec les sélecteurs CSS

Si vous avez la possibilité de collaborer avec les développeurs, la meilleure solution que je vous recommande très fortement est d’ajouter des attributs HTML personnalisés pour aider à identifier les éléments que vous devez sélectionner.

C’est une pratique populaire pour industrialiser les tests d’acceptation basés sur l’interface utilisateur, cette stratégie peut vraiment vous aider à avoir des tests UI plus stable et de minimiser les coûts de maintenance.

HTML5 a introduit un type d’attribut data-* formel dont nous pouvons tirer parti dans nos tests UI.

C’est très simple à mettre en place, il suffit d’ajouter un attribut personnalisé à vos composants HTML. Cet attribut sera utilisé uniquement pour localiser les éléments web pour les besoins de tests d’acceptation au niveau de l’UI.

Voici un simple exemple d’utilisation des attributs HTML personnalisés (data-testid):

username
<form name="login" id="login" action="/authenticate" method="post">
  <div class="row">
    <div class="large-6 small-12 columns">
      <label for="username">Username</label>
      <input data-testid="username" type="text" name="username" id="username" />
    </div>
  </div>
  <div class="row">
    <div class="large-6 small-12 columns">
      <label for="password">Password</label>
      <input
        data-testid="password"
        type="password"
        name="password"
        id="password"
      />
    </div>
  </div>
  <button data-testid="login-submit" class="radius" type="submit">
    <i class="fa fa-2x fa-sign-in"> Login</i>
  </button>
</form>

Dans cet exemple (login), j’ai ajouté un attribut data-testid à tous les éléments web utilisés par les tests UI.

Ce n’était pas forcément nécessaire d’ajouter les attributs HTML personnalisés (car nous avons déjà les ID username, password pour les champs username, password et nous avons aussi la classe radius pour le bouton login, mais je l’ai fait exprès 😀

Vous vous posez peut-être la question “Pourquoi ?

Le véritable avantage de cela est qu’il est beaucoup moins susceptible d’être modifié au cours de la durée de vie du projet.

Les autres attributs ID, name, class, etc. peuvent être changés par les développeurs et les raisons sont multiples:

  • Application des nouvelles règles de nommage
  • Changement de style CSS
  • Etc.

Mais un attribut personnalisé nommé avec data-testid est beaucoup moins susceptible d’être modifié sans avertissement.

Nous allons maintenant compter sur nos attributs HTML personnalisés (data-testid) pour sélectionner d’une manière simple et efficace les éléments web pour nos tests UI.

Nous pouvons donc utiliser les sélecteurs suivants pour sélectionner les éléments nécessaires pour notre page login:

  • [data-testid="username"]
  • [data-testid="password"]
  • [data-testid="login-submit"]

Mais pourquoi utiliser les sélecteurs CSS ?

C’est simple, quand vous rencontrez une personne qui préfère parler anglais, le plus simple est de parler anglais avec lui ! C’est le même principe ici, les développeurs d’une manière générale préfèrent la simplicité du CSS.

Conclusion

Le choix d’une stratégie de sélecteurs web est un élément essentiel au succès de l’automatisation des tests d’acceptation UI.

Il faut garder à l’esprit qu’un bon sélecteur possède les caractéristiques:

  • Unique
  • Descriptif
  • Faible probabilité de changement

Assurez-vous de:

  • Commencez par les deux stratégies ID et Class
  • Utilisez les sélecteurs CSS (ou XPath) lorsque vous devez parcourir plusieurs éléments
  • Discutez avec les développeurs pour trouver la meilleure solution possible

L’utilisation des attributs data-* avec les sélecteurs CSS reste la meilleure solution pour minimiser les coûts de maintenance et limiter les flaky tests.

Si vous avez aimé cet article, n’hésitez pas à le partager !

comments powered by Disqus