Automatisation des navigateurs web avec Selenium

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")

Étiquettes: Selenium WebDriver SeleniumIDE Grid CSS selectors

Publié le 10 juillet à 00h22