Guide Robot Framework — PerfShop¶
Ce guide vous apprend à écrire des scripts Robot Framework pour tester PerfShop dans le contexte de la stack QA pédagogique (Squash TM + Orchestrateur + Test Runner).
Infrastructure disponible¶
Votre script est exécuté sur le container perfshop-test-runner par l'orchestrateur Squash.
Ce container dispose des outils suivants :
Bibliothèques Robot Framework installées¶
| Bibliothèque | Usage |
|---|---|
RequestsLibrary |
Tests API HTTP |
SeleniumLibrary |
Tests navigateur (Chrome) |
JsonLibrary |
Manipulation JSON |
Collections |
Manipulation de listes/dicts |
OperatingSystem |
Lecture de fichiers, variables env |
BuiltIn |
Keywords natifs RF (toujours disponible) |
Outils système disponibles¶
| Outil | Version |
|---|---|
| Python | 3.11 |
| robot | 7.0 |
| pytest | 8.0 |
| git | installé (clone auto par l'orchestrateur) |
| Chrome | via Selenium Grid (perfshop-selenium) |
URLs disponibles dans vos scripts¶
Les URLs sont disponibles via les variables d'environnement du container. Vous pouvez les coder en dur — c'est tout à fait correct pour débuter.
URLs recommandées¶
| Cible | URL interne Docker | URL publique (prod NAS) |
|---|---|---|
| API backend | http://perfshop-app:8080 |
https://perfshop-api.perfshop.io |
| Frontend | http://perfshop-frontend |
https://perfshop.perfshop.io |
| Selenium Grid | http://perfshop-selenium:4444/wd/hub |
— (interne uniquement) |
💡 En local (Docker Desktop), utilisez les URLs internes Docker. En prod NAS, le formateur configure les URLs publiques automatiquement.
Lire l'URL depuis l'environnement (optionnel, avancé)¶
*** Test Cases ***
Mon Test
${api_url}= Evaluate os.environ.get('PUBLIC_API_URL', 'http://perfshop-app:8080') modules=os
Log URL API : ${api_url}
Structure minimale d'un script¶
*** Settings ***
Library RequestsLibrary
*** Variables ***
${API_URL} http://perfshop-app:8080
*** Test Cases ***
Mon premier test PerfShop
[Documentation] Description du test
[Tags] smoke api
Create Session perfshop ${API_URL}
${resp}= GET On Session perfshop url=/api/products params=page=0&size=5
Should Be Equal As Integers ${resp.status_code} 200
Log Réponse : ${resp.text}
Exemples de tests API¶
Vérifier que l'API répond¶
*** Settings ***
Library RequestsLibrary
*** Variables ***
${API_URL} http://perfshop-app:8080
*** Test Cases ***
CT-API-01 API produits repond
[Tags] smoke api
Create Session perfshop ${API_URL}
${resp}= GET On Session perfshop url=/api/products params=page=0&size=1
Should Be Equal As Integers ${resp.status_code} 200
${body}= Convert To String ${resp.content}
Should Contain ${body} price
Tester l'authentification¶
*** Settings ***
Library RequestsLibrary
Library Collections
*** Variables ***
${API_URL} http://perfshop-app:8080
${USER_EMAIL} user1@perfshop.com
${USER_PASS} password1
*** Test Cases ***
CT-AUTH-01 Login utilisateur
[Tags] auth
Create Session perfshop ${API_URL}
${payload}= Create Dictionary email=${USER_EMAIL} password=${USER_PASS}
${resp}= POST On Session perfshop url=/api/auth/login json=${payload}
Should Be Equal As Integers ${resp.status_code} 200
${body}= Set Variable ${resp.json()}
Should Be True ${body}[success]
Log Login OK pour ${USER_EMAIL}
Tester l'ajout au panier¶
*** Settings ***
Library RequestsLibrary
Library Collections
*** Variables ***
${API_URL} http://perfshop-app:8080
${USER_EMAIL} user1@perfshop.com
${USER_PASS} password1
*** Test Cases ***
CT-PANIER-01 Ajouter produit au panier
[Tags] panier fonctionnel
Create Session perfshop ${API_URL}
# Login
${creds}= Create Dictionary email=${USER_EMAIL} password=${USER_PASS}
${login}= POST On Session perfshop url=/api/auth/login json=${creds}
Should Be Equal As Integers ${login.status_code} 200
# Ajouter au panier (pas d authentification requise)
${item}= Create Dictionary productId=${1} quantity=${1}
${resp}= POST On Session perfshop url=/api/cart/add json=${item}
Should Be Equal As Integers ${resp.status_code} 200
Log Produit ajouté au panier
Vérifier un prix spécifique¶
*** Settings ***
Library RequestsLibrary
*** Variables ***
${API_URL} http://perfshop-app:8080
*** Test Cases ***
CT-PRIX-01 Prix produit 1 coherent
[Tags] prix regression
Create Session api ${API_URL}
${resp}= GET On Session api url=/api/products/1
Should Be Equal As Integers ${resp.status_code} 200
${product}= Set Variable ${resp.json()}
Should Be True ${product}[price] > 0
Log Prix du produit 1 : ${product}[price] €
Exemples de tests Selenium (navigateur)¶
⚠️ Les tests Selenium nécessitent que le container
perfshop-seleniumsoit démarré. Le formateur s'en charge — vous n'avez rien à configurer.
Ouvrir la page produits et vérifier le chargement¶
*** Settings ***
Library SeleniumLibrary
*** Variables ***
${SELENIUM_URL} http://perfshop-selenium:4444/wd/hub
${FRONTEND_URL} http://perfshop-frontend
*** Test Cases ***
CT-UI-01 Page produits charge correctement
[Tags] ui selenium
Open Browser ${FRONTEND_URL}/products browser=chrome
... remote_url=${SELENIUM_URL}
... options=add_argument("--no-sandbox");add_argument("--disable-dev-shm-usage")
Wait Until Page Contains Catalogue Produits timeout=15s
Page Should Contain produit
Close All Browsers
Se connecter via l interface¶
*** Settings ***
Library SeleniumLibrary
*** Variables ***
${SELENIUM_URL} http://perfshop-selenium:4444/wd/hub
${FRONTEND_URL} http://perfshop-frontend
*** Test Cases ***
CT-UI-02 Connexion utilisateur
[Tags] ui auth
Open Browser ${FRONTEND_URL}/login browser=chrome
... remote_url=${SELENIUM_URL}
... options=add_argument("--no-sandbox");add_argument("--disable-dev-shm-usage")
Input Text css:input[type="email"] user1@perfshop.com
Input Text css:input[type="password"] password1
Click Button css:button[type="submit"]
Wait Until Page Contains Catalogue timeout=10s
Close All Browsers
Prérequis à connaître pour PerfShop¶
1. Le Selenium Grid est interne¶
Le navigateur Chrome tourne dans le container perfshop-selenium, pas sur votre machine.
→ Toujours utiliser remote_url=http://perfshop-selenium:4444/wd/hub
2. Le frontend est une SPA React¶
La page React charge les données après le rendu initial.
→ Toujours utiliser Wait Until Element Is Visible ou Wait Until Page Contains
→ Ne jamais utiliser Get Text immédiatement après Open Browser
# Mauvais — trop rapide
Open Browser ${FRONTEND_URL}/products browser=chrome remote_url=${SELENIUM_URL}
${text}= Get Text css:.product-card # FAIL : pas encore chargé
# Correct
Open Browser ${FRONTEND_URL}/products browser=chrome remote_url=${SELENIUM_URL}
Wait Until Page Contains Catalogue Produits timeout=15s
Sleep 1s # laisser React finir de rendre
${text}= Get Text css:.product-name
3. Le panier est en mémoire React¶
Le panier PerfShop est un state React local (pas de localStorage).
→ Si vous naviguez avec Go To (rechargement de page), le panier se vide
→ Utiliser le lien navbar React pour conserver le panier
# Mauvais — recharge l app React et vide le panier
Go To ${FRONTEND_URL}/cart
# Correct — navigation SPA (préserve le state React)
Click Element xpath=//a[contains(text(),'Panier')]
4. L'API panier ne nécessite pas d'authentification¶
5. Comptes de test disponibles¶
| Mot de passe | |
|---|---|
user1@perfshop.com |
password1 |
user2@perfshop.com |
password2 |
| ... | ... |
user10@perfshop.com |
password10 |
perf.test1@perfshop.com |
TestPerf123! |
Déposer et exécuter votre script¶
Option 1 — Via Filebrowser (recommandé)¶
- Ouvrir Filebrowser (URL fournie par le formateur)
- Déposer votre fichier
.robotdans le dossier/scripts - Dans Squash TM → créer un cas de test avec la référence
perfshop-tests/votre-script.robot
Option 2 — Via Git¶
- Cloner le dépôt
perfshop-testsdepuis le GitLab PerfShop - Ajouter votre script dans le dossier racine
- Committer et pousser sur la branche
main - Squash TM récupérera automatiquement le nouveau script
Option 3 — Test direct (sans Squash TM)¶
Depuis le NAS ou en SSH sur le formateur :
Nomenclature recommandée¶
| Élément | Convention | Exemple |
|---|---|---|
| Fichier | CT-XXX-nom-court.robot |
CT-003-auth-login.robot |
| Nom du test | Description en clair | CT-003 Authentification utilisateur |
| Tags | minuscules, sans espace | smoke, api, ui, auth, panier |
| Variables | MAJUSCULES | ${API_URL}, ${TIMEOUT} |
| Keywords custom | Verbe + Nom | Verifier Prix Produit, Se Connecter |
Erreurs fréquentes¶
Element not found after Xs¶
L'élément n'est pas encore visible — React charge les données en asynchrone.
→ Augmenter le timeout : Wait Until Element Is Visible css:.mon-element timeout=20s
Connection refused sur l'API¶
L'URL de l'API est incorrecte ou le container perfshop-app n'est pas démarré.
→ Vérifier avec le formateur que les containers sont up
Session does not exist¶
Le navigateur Chrome a crashé ou la session Selenium a expiré.
→ Toujours utiliser [Teardown] Close All Browsers dans vos tests
StaleElementReferenceException¶
React a re-rendu le DOM entre deux actions Selenium.
→ Ajouter Sleep 1s ou re-récupérer l'élément après chaque action lente
Template complet prêt à l'emploi¶
*** Settings ***
# Mon test PerfShop
# Reference Squash TM : perfshop-tests/CT-XXX-mon-test.robot
Library RequestsLibrary
Library Collections
*** Variables ***
${API_URL} http://perfshop-app:8080
*** Test Cases ***
CT-XXX Mon test
[Documentation] Description de ce que teste ce script
[Tags] mon-tag api
# Etape 1 - preparation
Create Session perfshop ${API_URL}
# Etape 2 - action
${resp}= GET On Session perfshop url=/api/products params=page=0&size=1
# Etape 3 - verification
Should Be Equal As Integers ${resp.status_code} 200
Log Test OK
Ressources¶
- Documentation Robot Framework officielle
- RequestsLibrary
- SeleniumLibrary
- Dépôt des scripts :
https://perfshop-gitlab.perfshop.io/perf/perfshop-tests
Bibliothèque de sélecteurs lib/PerfShopSelectors.py¶
Pourquoi cette bibliothèque existe¶
Les tests Selenium ont besoin de sélecteurs XPath/CSS pour trouver les éléments dans le DOM React. Le frontend PerfShop étant en état livrable stabilisé, tous les sélecteurs ont été centralisés dans un fichier unique de bibliothèque — les étudiants n'ont pas à les écrire ou à les chercher.
scripts/
├── lib/ ← Bibliothèque (ne pas modifier)
│ ├── PerfShopSelectors.py ← 174 sélecteurs, FR + EN
│ └── i18n/
│ ├── fr.json ← textes FR
│ └── en.json ← textes EN
├── CT-002-prix-coherence.robot
├── CT-011-parcours-metier-ui.robot
└── ...
Utiliser la bibliothèque dans un script .robot¶
*** Settings ***
Library SeleniumLibrary
Variables ${CURDIR}/lib/PerfShopSelectors.py
*** Test Cases ***
Mon test UI
Open Browser http://perfshop-frontend/products browser=chrome
... remote_url=http://perfshop-selenium:4444/wd/hub
Wait Until Element Is Visible ${NAV_CART} timeout=15s
Click Element ${ADD_TO_CART_FIRST}
Click Element ${CART_LINK}
Wait Until Element Is Visible ${CART_ITEM} timeout=10s
Variables disponibles par page¶
| Section | Variables clés |
|---|---|
| Navbar | ${NAV_CART}, ${NAV_LOGIN}, ${NAV_LOGOUT}, ${NAV_ORDERS} |
| Catalogue | ${PRICE_STYLE_XPATH}, ${ADD_TO_CART_FIRST}, ${SEARCH_INPUT} |
| Panier | ${CART_ITEM}, ${CART_ITEM_PRICE}, ${CART_CHECKOUT_BTN} |
| Login | ${LOGIN_EMAIL_INPUT}, ${LOGIN_PWD_INPUT}, ${LOGIN_SUBMIT_BTN} |
| Checkout | ${CHECKOUT_STREET}, ${CHECKOUT_NEXT_BTN}, ${CONFIRM_ORDER_BTN} |
| Livraison | ${SHIPPING_STANDARD}, ${SHIPPING_EXPRESS}, ${SHIPPING_PREMIUM} |
| Paiement | ${PAYMENT_CARDNUMBER}, ${PAYMENT_CVV}, ${PAYMENT_MONTH_SEL} |
| Mes commandes | ${ORDERS_PAGE_TITLE}, ${ORDERS_FIRST_ROW}, ${MODAL_CLOSE_BTN} |
| Profil | ${PROFILE_EDIT_BTN}, ${PROFILE_SAVE_BTN}, ${PROFILE_INPUT_FIRSTNAME} |
Convention des préfixes
Chaque variable contient déjà son préfixe — utilisez-la directement sans en rajouter :
Click Element ${CART_LINK} ← correct (contient déjà "css:")
Click Element css:${CART_LINK} ← incorrect (double préfixe)
${PRICE_STYLE_XPATH}, ${ADD_TO_CART_FIRST},
${ORDER_NUMBER_TEXT}) nécessitent xpath= explicite :
Utiliser les sélecteurs en Python (pytest)¶
import sys
sys.path.insert(0, '/scripts')
from lib.PerfShopSelectors import SEL, css, xpath
from selenium.webdriver.common.by import By
# css() retire le préfixe "css:" pour By.CSS_SELECTOR
driver.find_element(By.CSS_SELECTOR, css(SEL.CART_LINK))
# xpath() retire le préfixe "xpath=" pour By.XPATH
driver.find_element(By.XPATH, xpath(SEL.ORDERS_FIRST_ROW))
# Les RAW XPath s'utilisent directement avec By.XPATH
driver.find_element(By.XPATH, SEL.PRICE_STYLE_XPATH)
Support FR / EN¶
Les sélecteurs basés sur du texte s'adaptent automatiquement à PERFSHOP_LANG.
PERFSHOP_LANG=fr → ADD_TO_CART_FIRST = (//button[contains(text(),'Ajouter au panier')])[1]
PERFSHOP_LANG=en → ADD_TO_CART_FIRST = (//button[contains(text(),'Add to cart')])[1]
Pièges spécifiques à PerfShop¶
❌ Piège 1 — Go To vide le panier¶
Le panier est un useState React — il est perdu à chaque rechargement de page.
# ❌ MAUVAIS — recharge React, panier perdu
Go To http://perfshop-frontend/login
# ✅ CORRECT — navigation SPA, panier conservé
Click Element ${NAV_LOGIN}
Règle : toujours naviguer par clic sur les liens navbar entre les pages de PerfShop.
❌ Piège 2 — Champs pré-remplis depuis le profil¶
Le checkout pré-remplit l'adresse depuis le profil utilisateur.
Input Text ajoute le texte après le contenu existant si le champ n'est pas vidé.
# ❌ MAUVAIS — accumule le texte existant + le nouveau
Input Text ${CHECKOUT_STREET} 12 rue de la Performance
# ✅ CORRECT — vider avant de taper
Press Keys ${CHECKOUT_STREET} CTRL+a
Input Text ${CHECKOUT_STREET} 12 rue de la Performance
❌ Piège 3 — Cliquer sous un modal ouvert¶
Quand un modal est ouvert, son overlay z-index: 1000 bloque tous les clics.
Selenium lève ElementClickInterceptedException.
# ❌ MAUVAIS — modal ouvert, logout bloqué
Click Element ${NAV_LOGOUT}
# ✅ CORRECT — fermer le modal, attendre sa disparition, puis agir
Click Element ${MODAL_CLOSE_BTN}
Wait Until Element Is Not Visible ${MODAL_DETAIL} timeout=10s
Click Element ${NAV_LOGOUT}
❌ Piège 4 — Couleurs hex vs rgb() dans les sélecteurs¶
React injecte les couleurs directes (background, color) en rgb() dans le DOM.
# ❌ MAUVAIS — React génère rgb(), pas hex
xpath=//button[contains(@style,'#10b981')]
# ✅ CORRECT — utiliser rgb()
xpath=//button[contains(@style,'rgb(16, 185, 129)')]
# ✅ ENCORE MIEUX — texte du bouton, invariant au rendu CSS
xpath=//button[contains(text(),'Passer la commande')]
Règle : pour les boutons d'action, préférer le texte au style CSS.
❌ Piège 5 — Popups Chrome non désactivées¶
Chrome ouvre des popups natives (enregistrer mot de passe, carte, notifications)
qui bloquent les clics. Les désactiver via add_experimental_option :
Open Browser ${URL} browser=chrome
... remote_url=${SELENIUM_URL}
... options=add_argument("--no-sandbox");add_argument("--disable-dev-shm-usage");add_argument("--disable-notifications");add_experimental_option("prefs", {"credentials_enable_service": False, "profile.password_manager_enabled": False, "autofill.credit_card_enabled": False, "autofill.profile_enabled": False, "profile.default_content_setting_values.notifications": 2})
| Option prefs | Popup désactivée |
|---|---|
credentials_enable_service: False |
"Enregistrer le mot de passe ?" |
autofill.credit_card_enabled: False |
"Enregistrer la carte ?" |
autofill.profile_enabled: False |
Autofill des formulaires |
notifications: 2 |
Popups de permission notifications |
Script de référence — CT-011 Parcours métier complet¶
Le script CT-011-parcours-metier-ui.robot couvre le parcours client complet en 10 étapes :
| Étape | Keyword | Ce qui se passe dans Chrome |
|---|---|---|
| T01 | T01 Homepage |
Catalogue chargé, SearchBar visible, prix affichés |
| T02 | T02 Search Product |
Saisie SearchBar, debounce 300ms, résultats filtrés |
| T03 | T03 Add To Cart |
Clic bouton, compteur navbar Panier (0) → (1) |
| T04 | T04 Login |
Clic lien navbar (SPA, panier conservé), formulaire, submit |
| T05 | T05 Acces Checkout |
Clic Panier, clic .btn-checkout |
| T06 | T06 Renseigner Adresse |
Étape 1 : vider + remplir 4 champs, clic Suivant |
| T07 | T07 Choisir Livraison |
Étape 2 : clic carte livraison, clic Suivant |
| T08 | T08 Renseigner Paiement |
Étape 3 : carte Luhn 4532 0151 1283 0366, CVV |
| T09 | T09 Confirmer Commande |
Étape 4 récap, scroll + clic bouton vert, confirmation |
| T10 | T10 Mes Commandes Et Logoff |
Commandes, modal détail, fermer modal, logout |
Un screenshot est capturé à chaque étape dans /rf-logs/T0X_*.png.