Vue d'ensemble du projet Selenium
Selenium est une suite complète d'outils et de bibliothèques destinée à l'automatisation des navigateurs web. Elle permet de contrôler les navigateurs via des scripts programmables pour des tâches telles que les tests fonctionnels ou le web scraping.
Composants principaux
- WebDriver : Exploite les API d'automatisation natives des navgiateurs pour un contrôle direct. Chaque navigateur dispose d'une implémentation spécifique appelée pilote, qui gère la communication entre le script et le navigateur.
- SeleniumIDE : Outil d'enregistrement d'actions sous forme d'extension pour Chrome et Firefox, permettant de créer rapidement des cas de test.
- Grid : Facilite l'exécution distribuée des tests sur plusieurs environnements (navigateurs, systèmes d'exploitation) à partir d'une machine locale.
Fonctionnement de WebDriver
WebDriver transmet des commandes au navigateur via un pilote et reçoit les réponses. Le pilote est un exécutable fourni par l'éditeur du navigateur. WebDriver ne contient aucune logique de test ; il nécessite un framework de test (comme JUnit, NUnit ou RSpec) pour orchestrer les scénarios et gérer les assertions.
Principes de conception de WebDriver
L'API WebDriver est conçue pour être concise et orientée objet, offrant une interface efficace pour piloter les navigateurs de manière programmatique.
Commandes fondamentales
Toutes les interactions avec Selenium reposent sur des commandes de base :
- Initialisation d'une session : ```
session_driver = webdriver.Chrome()
- Navigation vers une URL : ```
session_driver.get("https://exemple.com/formulaire")
- Récupération d'informations sur le navigateur : ```
titre_page = session_driver.title
- Configuration d'une attente implicite : ```
session_driver.implicitly_wait(0.5)
Cette méthode configure un délai pendant lequel WebDriver continuera à rechercher un élément non immédiatement présent. - Localisation d'éléments : ```
champ_saisie = session_driver.find_element(by=By.NAME, value="nom-champ")
bouton_validation = session_driver.find_element(by=By.CSS_SELECTOR, value="button[type='submit']")
- Interaction avec les éléments : ```
champ_saisie.send_keys("Selenium")
bouton_validation.click()
- Extraction de données d'un élément : ```
contenu_texte = message_element.text
- Terminaison de la session : ```
session_driver.quit()
Exemple complet
from selenium import webdriver
from selenium.webdriver.common.by import By
def test_scenario_form():
nav = webdriver.Chrome()
nav.get("https://exemple.com/formulaire-web")
assert nav.title == "Formulaire Web"
nav.implicitly_wait(0.5)
champ = nav.find_element(by=By.NAME, value="input-text")
btn = nav.find_element(by=By.CSS_SELECTOR, value="button.submit")
champ.send_keys("Selenium")
btn.click()
resultat = nav.find_element(by=By.ID, value="confirmation")
assert resultat.text == "Traitement réussi!"
nav.quit()
Options du pilote et stratégies de chargement
Les options permettent de configurer le comportemant du pilote, notamment la stratégie de chargement de page :
- normal (défaut) : Attend le déclenchement complet de l'événement
load. ``` options.page_load_strategy = 'normal' nav = webdriver.Chrome(options=options) - eager : Attend l'événement
DOMContentLoaded. ``` options.page_load_strategy = 'eager' nav = webdriver.Chrome(options=options) - none : Ne attend que le téléchargement initial du document HTML. ```
options.page_load_strategy = 'none'
nav = webdriver.Chrome(options=options)
Configuration du service du pilote
Le service du pilote permet de personnaliser les paramètres d'exécution :
- Port d'écoute : ```
service = webdriver.ChromeService(port=4567)
- Journaux : ```
service = webdriver.ChromeService(service_args=['--log-level=DEBUG'], log_output=subprocess.STDOUT)
ou via un fichier : ``` service = webdriver.ChromeService(log_output="/chemin/vers/logs.txt")
Les journaux du navigateur captent des événements variés : chargements de pages, erreurs JavaScript, requêtes réseau, etc., utiles pour le débogage.
Gestion des attentes
Attente implicite : Paramètre global affectant toutes les recherches d'éléments. Par défaut à 0, ce délai étend la recherche sur une durée spécifiée.
nav.implicitly_wait(2)
Attente explicite : Boucle conditionnellle qui vérifie une condition spécifique jusqu'à satisfaction ou timeout. Idéale pour des scénarios complexes.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(nav, 10).until(EC.presence_of_element_located((By.ID, "element-cible")))
Différences clés :
- L'attente explicite est ciblée et paramétrable par élément/condition.
- L'attente implicite s'applique de manière uniforme à toute la session.
Téléchargement de fichiers
Selenium contourne les boîtes de dialogue natives en utilisant send_keys sur les champs de type fichier :
input_fichier = nav.find_element(By.CSS_SELECTOR, "input[type='file']")
input_fichier.send_keys("/chemin/vers/fichier.pdf")
nav.find_element(By.ID, "bouton-upload").click()
Techniques de localisation avancées
Shadow DOM : Accès aux éléments encapsulés via shadow_root.
hote = nav.find_element(By.CSS_SELECTOR, "#shadow-host")
racine = hote.shadow_root
element_interne = racine.find_element(By.CSS_SELECTOR, ".contenu-cache")
Recherche d'éléments relatifs : Localisation basée sur des relations spatiales (au-dessus, en dessous, à gauche, à droite, près de).
from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with
localisateur = locate_with(By.TAG_NAME, "input").above({By.ID: "mot-de-passe"})
Propriétés des éléments
- Visibilité :
element.is_displayed() - État activé :
element.is_enabled() - Sélection :
element.is_selected() - Nom de balise :
element.tag_name - Dimensions et position :
element.rect - Styles CSS :
element.value_of_css_property('background-color') - Texte :
element.text - Attributs :
element.get_attribute("data-id")
Navigation dans le navigateur
nav.get("https://www.seleniumhq.org")
nav.get("https://www.seleniumhq.org/documentation")
titre = nav.title
nav.back() # Retour à la page précédente
nav.forward() # Avancer dans l'historique
nav.refresh() # Rechargement de la page
Multi-fenêtrage et onglets
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
avec webdriver.Chrome() as nav:
nav.get("https://site-exemple.com")
fenetre_originale = nav.current_window_handle
nav.find_element(By.LINK_TEXT, "Ouvrir dans un nouvel onglet").click()
WebDriverWait(nav, 10).until(EC.number_of_windows_to_be(2))
for handle in nav.window_handles:
if handle != fenetre_originale:
nav.switch_to.window(handle)
break
WebDriverWait(nav, 10).until(EC.title_is("Nouvelle page"))
Captures d'écran
Capture complète de la page ou d'un élément spécifique :
nav.save_screenshot("capture_page.png")
element_cible = nav.find_element(By.CSS_SELECTOR, "div.critique")
element_cible.screenshot("capture_element.png")