Implementación del patrón de objeto de página en Python + pytest

Cuando comencé a estudiar la automatización de pruebas, no pude entender: "¿Qué es Page Object y cómo implementarlo en Python + pytest?". Al estudiar Internet, encontré una implementación en otros idiomas y marcos: artículos educativos que me resultaban incomprensibles. Por lo tanto, decidí escribir este análisis. La idea es mostrar la implementación en Python + pytest y explicarla en un lenguaje accesible.


¿Qué es el objeto de página?


Este es un patrón popular que es el estándar de facto en la automatización de pruebas de productos web. La idea básica es separar la lógica de prueba de la implementación.


Cada página web del proyecto puede describirse como un objeto de clase. La interacción del usuario se describe en métodos de clase, y solo la lógica empresarial permanece en las pruebas. Este enfoque ayuda a evitar problemas con las pruebas al cambiar el diseño de una aplicación web. Debe corregir solo la clase que describe la página.


El objeto de página define las partes:


  • Página base \ Clase base: implementa los métodos necesarios para trabajar con webdriver.
  • Objeto de página \ Clase de página: implementa métodos para trabajar con elementos en páginas web.
  • Pruebas: implementa las pruebas descritas por la lógica empresarial del caso de prueba.

Esquema del patrón de objeto de página.
imagen
Para explicar claramente el tema, implementamos una prueba automatizada.


La parte teórica de la implementación.


Pasos :


  1. El usuario abre un navegador;
  2. El usuario ingresa https://ya.ru/ en la barra de direcciones;
  3. El usuario ingresa la palabra "Hola" en la barra de búsqueda;
  4. El usuario hace clic en el botón "Buscar".

Resultado esperado :
El usuario es redirigido a la búsqueda. Los resultados de la búsqueda tienen subelementos (video, imágenes, etc.).


Comprobar : en la página de búsqueda hay una barra de navegación y elementos de "imagen" y "video".


La parte práctica de la implementación.


Para comprender el artículo, debe conocer las construcciones básicas de Python, OOP, comprender los principios y funciones de Selenium.


Utilizaremos las bibliotecas: selenium y pytest. Puede instalarlos a través del administrador de paquetes pip.


pip install selenium pip install pytest 

Además, no olvide descargar el controlador para el navegador. Este artículo utiliza un controlador web de Chrome. Puedes descargarlo aquí . Para trabajar con él, coloque el archivo en el directorio raíz del proyecto.


Crear accesorio


Primero debe implementar la inicialización para WebDriver. Lo describiremos en accesorios. Los accesorios en pytest son funciones que tienen su propia periodicidad de ejecución.
Este es un reemplazo alternativo para los métodos SetUp y TearDown en unittest. Usando accesorios, puede preparar el estado inicial del sistema para la prueba.


En pytest hay un nombre reservado para el archivo de dispositivo: conftest.py .


Creamos el archivo conftest.py e implementamos la función con el nombre - browser.


Lo marcamos con el decorador @ pytest.fixture y pasamos el parámetro de alcance con un valor de sesión. Esto significa que esta función de dispositivo se ejecutará solo 1 vez por sesión de prueba.


 import pytest from selenium import webdriver @pytest.fixture(scope="session") def browser(): driver = webdriver.Chrome(executable_path="./chromedriver") yield driver driver.quit() 

A continuación, describimos la parte que se ejecutará antes de las pruebas. Inicializa el controlador web con una indicación de dónde se encuentra el controlador cromado. A continuación, usamos la construcción de rendimiento, que divide la función en partes, antes de las pruebas y después de las pruebas.


En la parte "después de las pruebas", llamamos a la función de salida, que finaliza la sesión y mata la instancia del controlador web.


Página base


Cree el archivo BaseApp.py. En la clase BasePage, definimos los métodos básicos para trabajar con WebDriver.


 from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class BasePage: def __init__(self, driver): self.driver = driver self.base_url = "https://ya.ru/" def find_element(self, locator,time=10): return WebDriverWait(self.driver,time).until(EC.presence_of_element_located(locator), message=f"Can't find element by locator {locator}") def find_elements(self, locator,time=10): return WebDriverWait(self.driver,time).until(EC.presence_of_all_elements_located(locator), message=f"Can't find elements by locator {locator}") def go_to_site(self): return self.driver.get(self.base_url) 

En la clase BasePage, cree un constructor que acepte un controlador, una instancia de webdriver. Especifique base_url, que se usará para abrir la página.


A continuación, creamos los métodos find_element (busca un elemento y lo devuelve) y find_elements (busca el conjunto y lo devuelve como una lista).


Este es un contenedor sobre WebdriverWait, que es responsable de las expectativas explícitas en Selenium.


En la función, determinamos el tiempo, que por defecto es de 10 segundos. Este es el momento de buscar el artículo. Método Go_to_site: llama a la función get desde WebDriver. El método le permite ir a la página indicada. Le pasamos base_url.


Objeto de página


Nuestra clase de página web se implementa en el archivo YandexPages.py.


 from BaseApp import BasePage from selenium.webdriver.common.by import By class YandexSeacrhLocators: LOCATOR_YANDEX_SEARCH_FIELD = (By.ID, "text") LOCATOR_YANDEX_SEARCH_BUTTON = (By.CLASS_NAME, "search2__button") LOCATOR_YANDEX_NAVIGATION_BAR = (By.CSS_SELECTOR, ".service__name") class SearchHelper(BasePage): def enter_word(self, word): search_field = self.find_element(YandexSeacrhLocators.LOCATOR_YANDEX_SEARCH_FIELD) search_field.click() search_field.send_keys(word) return search_field def click_on_the_search_button(self): return self.find_element(YandexSeacrhLocators.LOCATOR_YANDEX_SEARCH_BUTTON,time=2).click() def check_navigation_bar(self): all_list = self.find_elements(YandexSeacrhLocators.LOCATOR_YANDEX_NAVIGATION_BAR,time=2) nav_bar_menu = [x.text for x in all_list if len(x.text) > 0] return nav_bar_menu 

Creamos la clase YandexSeacrhLocators. Solo será para almacenar localizadores.
En la clase, describimos los localizadores:


LOCATOR_YANDEX_SEARCH_FIELD - buscar el localizador de cadenas
LOCATOR_YANDEX_SEARCH_BUTTON - localizador del botón "Buscar"
LOCATOR_YANDEX_NAVIGATION_BAR - localizador de barra de navegación (imágenes, videos, etc.)


Cree una clase SearchHelper, herede de BasePage.


Implementamos métodos auxiliares para trabajar con búsqueda:
enter_word: busca un elemento de la cadena de búsqueda, hace clic e ingresa la palabra deseada en la búsqueda;
click_on_the_search_button - Busca un elemento del botón de búsqueda y hace clic en él;
check_navigation_bar: busca elementos de navegación y obtiene el atributo de texto. Crea una lista y filtra por condición. Si la longitud de la cadena es mayor que cero, agrega el elemento a la lista. Por ejemplo, redefina el tiempo predeterminado configurándolo en 2 segundos.


Pruebas


 from YandexPages import SearchHelper def test_yandex_search(browser): yandex_main_page = SearchHelper(browser) yandex_main_page.go_to_site() yandex_main_page.enter_word("Hello") yandex_main_page.click_on_the_search_button() elements = yandex_main_page.check_navigation_bar() assert "" and "" in elements 

Creamos la función de prueba test_yandex_seacrh, que aceptará el accesorio del navegador. A continuación, la primera línea crea el objeto de página: yandex_main_page. Desde el objeto, llamamos métodos para interactuar con los elementos de la página. La función describe la lógica de nivel superior de las acciones del usuario.


Vamos a transferir todo lo que implementamos al esquema, similar al esquema de Objeto de página. Cambie el nombre de los bloques bajo el nombre de los archivos del artículo.


imagen


Como puede ver, pudimos poner en práctica el patrón.


Dejaré un enlace al repositorio terminado. Gracias por leer!

Source: https://habr.com/ru/post/472156/


All Articles