Implementando o padrão Objeto de Página no Python + pytest

Quando comecei a estudar a automação de testes, não conseguia entender - “o que é o Objeto de Página e como implementá-lo no Python + pytest?”. Estudando a Internet, encontrei uma implementação em outros idiomas e estruturas: artigos educacionais que eram incompreensíveis para mim. Por isso, decidi escrever esta análise. A idéia é mostrar a implementação em Python + pytest e explicá-la em uma linguagem acessível.


O que é objeto de página


Esse é um padrão popular que é o padrão de fato na automação de testes de produtos da web. A idéia básica é separar a lógica de teste da implementação.


Cada página da web do projeto pode ser descrita como um objeto de classe. A interação do usuário é descrita nos métodos de classe e apenas a lógica de negócios permanece nos testes. Essa abordagem ajuda a evitar problemas com testes ao alterar o layout de um aplicativo da web. Você precisa corrigir apenas a classe que descreve a página.


O objeto Página define as partes:


  • Página Base \ Classe Base - Implementa os métodos necessários para trabalhar com o webdriver.
  • Objeto de página \ Classe de página - Implementa métodos para trabalhar com elementos em páginas da web.
  • Testes - implementa os testes descritos pela lógica de negócios do caso de teste.

Esquema do padrão de Objeto de Página.
imagem
Para explicar claramente o tópico, implementamos um teste automatizado.


A parte teórica da implementação


Passos :


  1. O usuário abre um navegador;
  2. O usuário digita https://ya.ru/ na barra de endereço;
  3. O usuário digita a palavra "Olá" na barra de pesquisa;
  4. O usuário clica no botão "Localizar".

Resultado esperado :
O usuário é redirecionado para a pesquisa. Os resultados da pesquisa têm subitens (vídeo, fotos etc.).


Verifique : na página de pesquisa, há uma barra de navegação e elementos de “imagem” e “vídeo”.


A parte prática da implementação


Para entender o artigo, você precisa conhecer as construções básicas do Python, OOP, entender os princípios e funções do Selenium.


Usaremos as bibliotecas: selenium e pytest. Você pode instalá-los através do gerenciador de pacotes pip.


pip install selenium pip install pytest 

Também não se esqueça de baixar o driver para o navegador. Este artigo usa o Chrome Webdriver. Você pode baixá-lo aqui . Para trabalhar com ele, coloque o arquivo no diretório raiz do projeto.


Criar acessório


Primeiro, você precisa implementar a inicialização do WebDriver. Vamos descrevê-lo em jogos. As luminárias no pytest são funções que têm sua própria periodicidade de execução.
Esta é uma substituição alternativa para os métodos SetUp e TearDown em unittest. Usando acessórios, você pode preparar o estado inicial do sistema para teste.


No pytest, existe um nome reservado para o arquivo de fixação - conftest.py .


Criamos o arquivo conftest.py e implementamos a função com o nome - browser.


Marcamos com o decorador @ pytest.fixture e passamos o parâmetro scope com um valor de session. Isso significa que essa função de fixação será executada apenas 1 vez por sessão de teste.


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

A seguir, descrevemos a parte que será executada antes dos testes. Inicializa o webdriver com uma indicação de onde o chromedriver está localizado. Em seguida, usamos o construto yield, que divide a função em partes - antes e depois dos testes.


Na parte "pós-teste", chamamos a função quit, que finaliza a sessão e mata a instância do webdriver.


Página base


Crie o arquivo BaseApp.py. Na classe BasePage, definimos os métodos básicos para trabalhar com o 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) 

Na classe BasePage, crie um construtor que aceite um driver - uma instância do webdriver. Especifique base_url, que será usado para abrir a página.


Em seguida, criamos os métodos find_element (procura por um elemento e o retorna) e find_elements (procura pelo conjunto e retorna como uma lista).


Este é um invólucro do WebdriverWait, responsável por expectativas explícitas no Selenium.


Na função, determinamos o tempo, que por padrão é de 10 segundos. Este é o momento de procurar o item. Método Go_to_site - Chama a função get do WebDriver. O método permite que você vá para a página indicada. Passamos base_url para ele.


Objeto de página


Nossa classe de página da web é implementada no arquivo 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 

Criamos a classe YandexSeacrhLocators. Será apenas para armazenar localizadores.
Na classe, descrevemos os localizadores:


LOCATOR_YANDEX_SEARCH_FIELD - pesquisar localizador de string
LOCATOR_YANDEX_SEARCH_BUTTON - localizador do botão "Localizar"
LOCATOR_YANDEX_NAVIGATION_BAR - localizador de barra de navegação (fotos, vídeos etc.)


Crie uma classe SearchHelper, herdada de BasePage.


Implementamos métodos auxiliares para trabalhar com a pesquisa:
enter_word - pesquisa um elemento da string de pesquisa, clica e insere a palavra desejada na pesquisa;
click_on_the_search_button - Procura um elemento do botão de pesquisa e clica nele;
check_navigation_bar - Procura itens de navegação e obtém o atributo de texto. Cria uma lista e filtra por condição. Se o comprimento da string for maior que zero, adicione o item à lista. Por exemplo, redefina o tempo padrão configurando-o para 2 segundos.


Testes


 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 

Criamos a função de teste test_yandex_seacrh, que aceitará o acessório do navegador. Em seguida, a primeira linha cria o objeto de página - yandex_main_page. A partir do objeto, chamamos métodos para interagir com os elementos da página. A função descreve a lógica de nível superior das ações do usuário.


Vamos transferir tudo o que implementamos no esquema, semelhante ao esquema de objeto de página. Renomeie os blocos com o nome dos arquivos do artigo.


imagem


Como você pode ver, conseguimos colocar o padrão em prática.


Deixarei um link para o repositório concluído. Obrigado pela leitura!

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


All Articles