
Problèmes de synchronisation (waits) : `Wait Until Page Contains`, `Sleep` (à utiliser avec parcimonie)
Apprenez à résoudre les problèmes de synchronisation dans Robot Framework avec des attentes explicites comme 'Wait Until Page Contains' et l'usage prudent de 'Sleep'.
Comprendre l'importance de la synchronisation dans les tests web
L'un des aspects les plus critiques et souvent délicats de l'automatisation des tests d'interfaces web est la synchronisation. Les applications web modernes sont dynamiques : le contenu se charge de manière asynchrone, des éléments apparaissent, disparaissent ou changent d'état en réponse à des actions de l'utilisateur ou à des événements du serveur. Un script d'automatisation, par nature, s'exécute séquentiellement et souvent très rapidement. Si le script tente d'interagir avec un élément avant qu'il ne soit prêt (par exemple, avant qu'il ne soit chargé dans le DOM, visible, ou cliquable), le test échouera, typiquement avec une erreur "Element not found" ou similaire. Ces échecs dus à un mauvais timing sont une source majeure d'instabilité et de tests "flaky" (non fiables, qui échouent de manière intermittente).
La synchronisation consiste donc à s'assurer que le script de test attend que l'application soit dans l'état attendu avant de tenter une interaction ou une vérification. Il ne s'agit pas simplement de ralentir les tests, mais de les rendre intelligents et adaptatifs face à la nature parfois imprévisible des temps de chargement et des mises à jour de l'interface utilisateur.
Robot Framework, notamment via SeleniumLibrary, fournit plusieurs mécanismes pour gérer la synchronisation. Une mauvaise gestion des attentes est souvent la cause première des tests qui fonctionnent sur la machine d'un développeur mais échouent en intégration continue, ou qui réussissent neuf fois sur dix. Maîtriser les techniques de synchronisation est donc fondamental pour construire des suites de tests automatisés robustes et fiables.
Les attentes explicites : la stratégie recommandée
La méthode la plus robuste et recommandée pour gérer la synchronisation est l'utilisation d'attentes explicites (explicit waits). Une attente explicite est un morceau de code qui définit une condition spécifique à attendre et un délai maximum (timeout). Le script attendra que cette condition soit remplie, ou que le délai soit écoulé, avant de continuer. Si la condition est remplie avant la fin du délai, le script continue immédiatement, ce qui rend les tests plus efficaces que l'utilisation de pauses fixes.
SeleniumLibrary offre une riche collection de keywords pour implémenter des attentes explicites. Ces keywords commencent souvent par "Wait Until...". Voici quelques exemples parmi les plus utilisés :
Wait Until Page Contains Element: Attend qu'un élément spécifié par un sélecteur soit présent dans le DOM de la page.Wait Until Element Is Visible: Attend qu'un élément, déjà présent dans le DOM, devienne visible à l'utilisateur.Wait Until Element Is Enabled: Attend qu'un élément (typiquement un bouton ou un champ de saisie) devienne activé.Wait Until Element Contains: Attend que le texte d'un élément contienne une chaîne spécifique.Wait Until Page Contains: Attend que le texte source de la page contienne une chaîne spécifique.Wait Until Location Is: Attend que l'URL actuelle du navigateur corresponde à une URL attendue.Wait Until Keyword Succeeds: Un keyword très puissant qui permet d'attendre qu'un autre keyword (ou une série de keywords) s'exécute avec succès, en le réessayant pendant un certain temps.
L'utilisation typique implique d'appeler l'un de ces keywords juste avant l'interaction ou la vérification qui dépend de la condition. Par exemple, avant de cliquer sur un bouton qui apparaît après un chargement AJAX :
*** Test Cases ***
Mon Test Avec Attente Explicite
# ... étapes précédentes ...
Click Element id:boutonDeclencheurAjax
Wait Until Element Is Visible id:resultatAjax timeout=10s
${texte_resultat}= Get Text id:resultatAjax
Should Be Equal ${texte_resultat} Données chargées avec succèsLe paramètre timeout (optionnel, avec une valeur par défaut) spécifie la durée maximale d'attente. Si la condition n'est pas remplie dans ce délai, le keyword échoue, indiquant un problème potentiel avec l'application ou un délai d'attente trop court.
Le keyword `Sleep` : à utiliser avec une extrême parcimonie
Le keyword Sleep, disponible dans la librairie BuiltIn de Robot Framework, introduit une pause fixe et inconditionnelle dans l'exécution du test. Par exemple, Sleep 5s mettra le test en pause pendant exactement 5 secondes, quoi qu'il arrive sur la page.
*** Test Cases ***
Test Avec Sleep (Non Recommandé Pour La Synchro)
# ... étapes ...
Log To Console Début de la pause...
Sleep 3s # Mauvaise pratique si utilisé pour attendre un élément
Log To Console Fin de la pause.
# ... suite du test ...Bien que simple à utiliser, l'emploi de Sleep pour gérer la synchronisation est fortement déconseillé et est considéré comme une mauvaise pratique dans la majorité des cas. Pourquoi ?
- Inefficacité : Si l'élément ou la condition que vous attendez est prêt(e) après 1 seconde, mais que vous avez mis un
Sleep 5s, vous perdez 4 secondes inutilement. Multipliez cela par de nombreux tests, et la durée totale d'exécution de votre suite peut augmenter considérablement. - Manque de fiabilité : Si l'élément prend 6 secondes à apparaître à cause de conditions réseau lentes ou d'une charge serveur élevée, votre
Sleep 5sne sera pas suffisant, et le test échouera. Vous serez alors tenté d'augmenter la durée duSleep, le rendant encore plus inefficace dans les cas normaux. Les pauses fixes ne s'adaptent pas aux variations de performance de l'application ou de l'environnement. - Masquage de problèmes : Utiliser
Sleeppeut masquer des problèmes de performance réels de l'application ou des erreurs de conception dans les tests.
Alors, quand Sleep peut-il être acceptable ? Son usage est légitime dans de rares situations :
- Pour simuler un temps de réflexion utilisateur, bien que ce soit rarement nécessaire pour la validation fonctionnelle.
- Lors du débogage, pour ralentir délibérément l'exécution afin d'observer le comportement de l'application (mais
Pause Executionou les outils de débogage du navigateur sont souvent meilleurs pour cela). - Dans des cas très spécifiques où il n'existe aucune condition observable pour une attente explicite (par exemple, attendre qu'un processus en arrière-plan non visible se termine, bien que même là, il y ait souvent de meilleures approches).
En règle générale, si vous êtes sur le point d'utiliser Sleep pour attendre qu'un élément apparaisse ou qu'une action se termine, demandez-vous s'il n'y a pas un keyword "Wait Until..." qui pourrait faire le travail de manière plus intelligente et robuste.
Autres mécanismes d'attente et configurations
Outre les attentes explicites et Sleep, SeleniumLibrary possède un concept d'attente implicite (implicit wait). Celle-ci peut être configurée globalement lors de l'importation de la librairie ou via le keyword Set Selenium Implicit Wait. Une attente implicite indique à WebDriver de patienter un certain temps lors de la recherche d'un ou plusieurs éléments s'ils ne sont pas immédiatement disponibles. Par exemple :
*** Settings ***
Library SeleniumLibrary implicit_wait=5sAvec cette configuration, chaque fois que SeleniumLibrary essaie de trouver un élément (par exemple, pour Click Element ou Input Text), elle réessaiera pendant 5 secondes au maximum si l'élément n'est pas trouvé instantanément. Bien que cela puisse sembler pratique, l'utilisation généralisée des attentes implicites est parfois débattue. Elles peuvent ralentir les tests si de nombreux éléments ne sont pas trouvés (chaque recherche infructueuse attendra le délai complet) et peuvent rendre le débogage plus complexe car l'attente est "cachée". De plus, mélanger attentes implicites et explicites peut conduire à des comportements d'attente cumulatifs et imprévisibles. Beaucoup préfèrent désactiver l'attente implicite (implicit_wait=0s) et se fier exclusivement aux attentes explicites pour un contrôle plus fin.
SeleniumLibrary permet également de définir un timeout global pour la plupart de ses keywords d'interaction. Ce timeout, s'il est défini, est utilisé par défaut pour les keywords d'attente explicite si aucun timeout spécifique n'est fourni à l'appel du keyword. Il peut être défini lors de l'importation :
*** Settings ***
Library SeleniumLibrary timeout=10sOu dynamiquement avec Set Selenium Timeout. Cela peut aider à standardiser les délais d'attente à travers une suite de tests, mais il est toujours possible de surcharger ce timeout global en spécifiant un argument timeout directement au keyword d'attente si un cas particulier le nécessite.
Enfin, le keyword Wait Until Keyword Succeeds mérite une mention spéciale pour sa flexibilité. Il permet de répéter l'exécution d'un autre keyword (ou d'une séquence de keywords encapsulés dans un keyword utilisateur) jusqu'à ce qu'il réussisse ou qu'un délai soit écoulé. C'est extrêmement utile pour gérer des conditions de synchronisation complexes qui ne sont pas couvertes par les keywords "Wait Until Element..." standards. Par exemple, attendre qu'un appel API en arrière-plan mette à jour une valeur spécifique dans l'interface :
*** Keywords ***
Vérifier La Mise à Jour Asynchrone
${valeur_actuelle}= Get Text id:compteurMiseAJour
Should Be Equal As Integers ${valeur_actuelle} 100
*** Test Cases ***
Test Avec Wait Until Keyword Succeeds
# ... action qui déclenche la mise à jour ...
Wait Until Keyword Succeeds retry=10x retry_interval=2s Vérifier La Mise à Jour AsynchroneIci, Vérifier La Mise à Jour Asynchrone sera réessayé jusqu'à 10 fois, avec un intervalle de 2 secondes entre les tentatives, jusqu'à ce qu'il réussisse (c'est-à-dire que le compteur atteigne 100). Cette approche est puissante pour créer des points de synchronisation personnalisés et robustes.