[Selenium] Personnaliser la méthode apply de WebDriverWait

Mise en situation

Pimp my WebDriverWait

Comme nous l’avons vu dans l’article sur les Waits, la classe WebDriverWait est une spécialisation de la classe FluentWait. Cela nous donne la possibilité de surcharger la méthode until afin de lui faire faire plus de choses.

Prenons l’exemple d’une application où l’on peut importer un CSV qui va créer en base de données 500 produits. Il existe un datagrid qui liste ces produits et qui indique le nombre total de produits en base. Votre objectif est de savoir quand l’import est terminé (oui l’application ne le dit pas). Lorsque l’import est terminé le datagrid indique « 500 produits ».

On obtient le scénario suivant :

  • importer le CSV
  • aller sur le datagrid des produits
  • vérifier que le datagrid indique 500 produits

C’est la troisième étape qui nous intéresse.

On pourrait écrire le code suivant :

Assert.assertEqual(driver.findElement(By.id("nombre_produits")).getText(), "500 produits");

Si l’import est toujours en cours le test va échouer. On pourrait obtenir par exemple « 356 produits » au lieu de « 500 produits » et le test s’arrête là.

On pourrait aussi penser à faire :

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(60));
wait.until(ExpectedConditions.textToBePresentInElementLocated(By.id("nombre_produits"), "500 produits"));

Dans ce cas aussi on est confronté au même problème. Si l’import n’est pas terminé l’élément ne contiendra pas le texte « 500 produits ». En effet lorsque l’on va arriver sur la page l’élément « nombre_produits » contiendra un certain texte. On aura beau attendre 60 secondes, le texte affiché sera toujours le même. Il faudrait donc pouvoir rafraîchir la page tant que le timeout n’est pas atteint et vérifier si l’on obtient le texte attendu.

La surcharge et la lambda expression

Half-live logo

Voici le code qui va nous permettre de résoudre le problème. Notez l’utilisation de la lambda expression dans ce code. On en trouve un exemple dans la documentation de Selenium. Ça a d’ailleurs était pour moi l’occasion de faire une pull request dans le projet Github de la documentation.

boolean nombreProduitsOK = false;
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(60));
wait.pollingEvery(Duration.ofSeconds(5));

nombreProduitsOK = wait.until(driver -> {
    driver.navigate().refresh();
    return driver.findElement(By.id("nombre_produits")).getText().equals("500 produits");
});

Durand 60 secondes, toutes les 5 secondes, la page du datagrid est actualisée (notez le driver.navigate().refresh();) et on vérifie si l’élément affiche le texte « 500 produits ».

Si ce n’est pas le cas alors c’est reparti pour un tour. Dès que l’élément contient « 500 produits » on passe à la suite du test. Si au bout des 60 secondes l’élément ne contient toujours pas le texte « 500 produits » alors le test échouera et l’on pourra considérer que l’import n’a pas fonctionné.

Il faut adapter la valeur du timeout en fonction du temps que prend en général le traitement (en mettant une marge pour être tranquille).

C’est une possibilité bien sympathique que permet Selenium. Cela évite d’avoir recourt à sleep() pour s’adapter à des fonctionnements complexes.

Ressources

https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/ui/FluentWait.html#until(java.util.function.Function)

http://makeseleniumeasy.com/2017/06/06/part-3-waits-in-selenium-explicit-wait

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *