Recherche…


Introduction

Un rôle important dans l'automatisation des sites Web et des applications Web consiste à identifier les éléments à l'écran et à interagir avec eux. Les objets se trouvent dans Selenium grâce à l'utilisation de localisateurs et de la classe By . Ces localisateurs et interactions sont placés dans les objets de la page pour éviter le code en double et faciliter la maintenance. Il encapsule les WebElements et suppose de contenir le comportement et de renvoyer des informations sur la page (ou une partie d'une page dans une application Web).

Remarques

Le modèle d'objet de page est un modèle où l'on écrit des classes orientées objet qui servent d'interface à une vue particulière de la page Web. Nous utilisons les méthodes de cette classe de page pour effectuer l'action requise. Il y a quelques années, nous manipulions directement le code HTML de la page Web dans des classes de test, ce qui était très difficile à maintenir et risquait de provoquer des modifications de l'interface utilisateur.

Cependant, le fait d’avoir votre code organisé de la même manière que le modèle d’objets de page fournit une API spécifique à l’application, vous permettant de manipuler les éléments de la page sans contourner le HTML. Le principe de base de la page dit: votre objet page doit avoir tout ce qu’un humain peut faire sur cette page Web. Par exemple, pour accéder au champ de texte d'une page Web, vous devez utiliser une méthode pour obtenir le texte et retourner la chaîne après avoir effectué toutes les modifications.

Quelques points importants à retenir lors de la conception des objets de la page:

  1. L'objet de la page ne devrait généralement pas être construit uniquement pour les pages, mais vous devriez plutôt le construire pour des éléments significatifs de la page. Par exemple, une page comportant plusieurs onglets pour afficher différents graphiques de vos universitaires doit avoir le même nombre de pages que le nombre d'onglets.

  2. La navigation d'une vue à l'autre doit renvoyer l'instance des classes de page.

  3. Les méthodes utilitaires requises uniquement pour une vue ou une page Web spécifique doivent appartenir uniquement à cette classe de page.

  4. Les méthodes d'assertion ne doivent pas être prises en compte par les classes de page, vous pouvez avoir des méthodes pour renvoyer booléen sans les vérifier. Par exemple, pour vérifier le nom complet de l'utilisateur, vous pouvez avoir une méthode pour obtenir une valeur booléenne:

     public boolean hasDisplayedUserFullName (String userFullName) {
         return driver.findElement(By.xpath("xpathExpressionUsingFullName")).isDisplayed();
     }
    
  5. Si votre page Web est basée sur iframe, préférez également avoir des classes de page pour les iframes.

Avantages du modèle d'objet de page:

  1. Séparation propre entre le code de test et le code de page
  2. En cas de modification de l'interface utilisateur de la page Web, il n'est pas nécessaire de modifier votre code à plusieurs endroits. Changer uniquement dans les classes de page.
  3. Pas de localisateur d'éléments dispersés.
  4. Facilite la compréhension du code
  5. Entretien facile

Introduction (Utilisation de Java)

Un exemple pour effectuer un test de connexion basé sur le modèle d'objet de la page:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

/**
 * Class which models the view of Sign-In page
 */
public class SignInPage {
    
    @FindBy(id="username")
    private usernameInput;

    @FindBy(id="password")
    private passwordInput;

    @FindBy(id="signin")
    private signInButton;

    private WebDriver driver;

    public SignInPage(WebDriver driver) {
        this.driver = driver;
    }
    
    /**
     * Method to perform login
     */
    public HomePage performLogin(String username, String password) {
        usernameInput.sendKeys(username);
        passwordInput.sendKeys(password);
        signInButton.click();
        return PageFactory.initElements(driver, HomePage.class);
    }
}


import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
/**
 * Class which models the view of home page
 */
public class HomePage {
    @FindBy(id="logout")
    private logoutLink;

    private WebDriver driver;

    public HomePage(WebDriver driver) {
        this.driver = driver;
    }
    
    /**
     * Method to log out
     */
    public SignInPage logout() {
        logoutLink.click();
        wait.ForPageToLoad();
        return PageFactory.initElements(driver, SignInPage.class);
    }
}

/**
 * Login test class
 */
public class LoginTest {
    public void testLogin() {
        SignInPage signInPage = new SignInPage(driver);
        HomePage homePage = signInPage.login(username, password);
        signInPage = homePage.logout();
    }
}

C #

Les objets de page doivent contenir le comportement, renvoyer des informations pour les assertions et éventuellement une méthode pour la méthode d'état de page prête lors de l'initialisation. Selenium prend en charge les objets de page à l'aide d'annotations. En C # c'est comme suit:

using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;
using OpenQA.Selenium.Support.UI;
using System;
using System.Collections.Generic;

public class WikipediaHomePage
{
    private IWebDriver driver;
    private int timeout = 10;
    private By pageLoadedElement = By.ClassName("central-featured-logo");

    [FindsBy(How = How.Id, Using = "searchInput")]
    [CacheLookup]
    private IWebElement searchInput;

    [FindsBy(How = How.CssSelector, Using = ".pure-button.pure-button-primary-progressive")]
    [CacheLookup]
    private IWebElement searchButton;

    public ResultsPage Search(string query) 
    {
        searchInput.SendKeys(query);
        searchButton.Click();
    }

    public WikipediaHomePage VerifyPageLoaded() 
    {
        new WebDriverWait(driver, TimeSpan.FromSeconds(timeout)).Until<bool>((drv) =>  return drv.ExpectedConditions.ElementExists(pageLoadedElement));

        return this;
    }
}

Remarques:

  • CacheLookup enregistre l'élément dans le cache et enregistre le retour d'un nouvel élément à chaque appel. Cela améliore les performances mais ne permet pas de modifier dynamiquement les éléments.
  • searchButton a 2 noms de classes et pas d'ID, c'est pourquoi je ne peux pas utiliser le nom de la classe ou l'id.
  • J'ai vérifié que mes localisateurs me renverraient l'élément que je souhaite utiliser avec Developer Tools (pour Chrome). Dans d'autres navigateurs, vous pouvez utiliser FireBug ou similaire.
  • Search() méthode Search() renvoie un autre objet de page ( ResultsPage ) car le clic de recherche vous redirige vers une autre page.

Modèle d'objet de page Meilleures pratiques

  • Créez des fichiers séparés pour l'en-tête et le pied de page (car ils sont communs à toutes les pages et cela n'a aucun sens de les intégrer à une seule page)
  • Conserve les éléments communs (comme Search / Back / Next, etc.) dans un fichier séparé (L'idée est de supprimer tout type de duplication et de garder la ségrégation logique)
  • Pour Driver, c'est une bonne idée de créer une classe de pilote distincte et de garder le pilote statique afin de pouvoir l’accéder à toutes les pages! (J'ai toutes mes pages Web pour étendre DriverClass)
  • Les fonctions utilisées dans PageObjects sont décomposées en morceaux les plus petits possibles en tenant compte de la fréquence et de la manière dont elles seront appelées (la manière dont vous vous êtes connecté - bien que la connexion puisse être divisée en fonctions enterUsername et enterPassword comme la fonction de connexion est plus logique car dans la majorité des cas, la fonction de connexion est appelée plutôt que des appels séparés aux fonctions enterUsername et enterPassword)
  • L'utilisation de PageObjects lui-même sépare le script de test de elementLocators
  • Avoir des fonctions utilitaires dans un dossier utils séparé (comme DateUtil, excelUtils, etc.)
  • Avoir des configurations dans un dossier conf distinct (comme définir l'environnement sur lequel les tests doivent être exécutés, configurer les dossiers de sortie et d'entrée)
  • Incorporer screenCapture en cas d'échec
  • Avoir une variable d'attente statique dans DriverClass avec un temps d'attente implicite comme vous l'avez fait Essayez toujours d'avoir des attentes conditionnelles plutôt que des attentes statiques comme: wait.until (ExpectedConditions). Cela garantit que l'attente ne ralentit pas inutilement l'exécution.


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow