Buscar..


Introducción

Un papel importante en la automatización de sitios web y aplicaciones web implica identificar elementos en la pantalla e interactuar con ellos. Los artículos se encuentran en Selenium mediante el uso de localizadores y la clase By . Estos localizadores e interacciones se colocan dentro de los objetos de página como una mejor práctica para evitar duplicar el código y facilitar el mantenimiento. Encapsula WebElements y se supone que contiene información de comportamiento y devolución en la página (o parte de una página en una aplicación web).

Observaciones

El modelo de objetos de página es un patrón en el que escribimos clases orientadas a objetos que sirven como interfaz para una vista particular de la página web. Usamos los métodos de esa clase de página para realizar la acción requerida. Hace unos años, estábamos manipulando el código HTML de la página web en las clases de prueba directamente, lo cual era muy difícil de mantener junto con los cambios frágiles en la interfaz de usuario.

Sin embargo, tener su código organizado de una forma de Patrón de Objeto de Página proporciona una API específica para la aplicación, lo que le permite manipular los elementos de la página sin excavar alrededor del HTML. La Rue of Thumb básica dice, su objeto de página debe tener todo lo que un humano puede hacer en esa página web. Por ejemplo, para acceder al campo de texto en una página web, debe utilizar un método para obtener el texto y devolver la cadena después de realizar todas las modificaciones.

Algunos puntos importantes que debe tener en cuenta al diseñar los objetos de página:

  1. Por lo general, el objeto de página no debe compilarse solo para las páginas, pero usted prefiere compilarlo para elementos significativos de la página. Por ejemplo, una página con varias pestañas para mostrar diferentes gráficos de sus académicos debe tener el mismo número de páginas que el recuento de pestañas.

  2. La navegación de una vista a otra debe devolver la instancia de clases de página.

  3. Los métodos de utilidad que deben estar allí solo para una vista o página web específica deben pertenecer solo a esa clase de página.

  4. Los métodos de aserción no deben ser atendidos por clases de página, puede tener métodos para devolver booleanos pero no verificarlos allí. Por ejemplo, para verificar el nombre completo del usuario, puede tener un método para obtener un valor booleano:

     public boolean hasDisplayedUserFullName (String userFullName) {
         return driver.findElement(By.xpath("xpathExpressionUsingFullName")).isDisplayed();
     }
    
  5. Si su página web está basada en iframe, prefiera tener clases de página para iframes también.

Ventajas del patrón de objeto de página:

  1. Separación limpia entre el código de prueba y el código de página
  2. En caso de cualquier cambio en la interfaz de usuario de la página web, no es necesario cambiar el código en varios lugares. Cambiar solo en clases de pagina.
  3. No hay localizadores de elementos dispersos.
  4. Hace que el código sea más fácil de entender
  5. Facil mantenimiento

Introducción (Utilizando Java)

Un ejemplo para realizar una prueba de inicio de sesión basada en el patrón de objeto de página:

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();
    }
}

DO#

Los objetos de página deben contener comportamiento, información de retorno para las aserciones y posiblemente un método para el método de estado de preparación de página en la inicialización. Selenium soporta objetos de página usando anotaciones. En C # es como sigue:

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;
    }
}

notas:

  • CacheLookup guarda el elemento en el caché y guarda devolver un nuevo elemento cada llamada. Esto mejora el rendimiento pero no es bueno para elementos que cambian dinámicamente.
  • searchButton tiene 2 nombres de clase y no ID, por eso no puedo usar el nombre o la identificación de la clase.
  • Verifiqué que mis localizadores me devolverán el elemento que deseo usando las Herramientas de desarrollador (para Chrome), en otros navegadores puedes usar FireBug o similar.
  • Search() método Search() devuelve otro objeto de página ( ResultsPage ) cuando el clic de búsqueda lo redirecciona a otra página.

Página de Buenas Prácticas Modelo de Objeto

  • Cree archivos separados para el encabezado y el pie de página (ya que son comunes para todas las páginas y no tiene sentido hacer que formen parte de una sola página)
  • Mantenga los elementos comunes (como Buscar / Atrás / Siguiente, etc.) en un archivo separado (la idea es eliminar cualquier tipo de duplicación y mantener la segregación lógica)
  • Para Driver, es una buena idea crear una clase de Driver separada y mantener el Driver como estático para que se pueda acceder a él en todas las páginas. (Tengo todas mis páginas web extendidas DriverClass)
  • Las funciones utilizadas en PageObjects se dividen en la parte más pequeña posible teniendo en cuenta la frecuencia y la forma en que se llamarán (la forma en que lo hizo para iniciar sesión, aunque el inicio de sesión se puede dividir en enterUsername y enterPassword, pero aún así se mantiene ya que la función de inicio de sesión es más lógica porque en la mayoría de los casos, la función de inicio de sesión se llamará en lugar de llamadas separadas para ingresar las funciones de nombre de usuario y contraseña.
  • El uso de PageObjects en sí mismo separa el script de prueba de los elementLocators
  • Tener funciones de utilidad en carpetas utils separadas (como DateUtil, excelUtils, etc.)
  • Tener configuraciones en una carpeta conf separada (como establecer el entorno en el que se deben ejecutar las pruebas, configurar las carpetas de salida y entrada)
  • Incorporar screenCapture en caso de fallo.
  • Tenga una variable de espera estática en DriverClass con un tiempo de espera implícito como lo ha hecho Siempre intente tener esperas condicionales en lugar de esperas estáticas como: wait.until (ExpectedConditions). Esto asegura que la espera no ralentiza la ejecución innecesariamente.


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow