Article image
Regilene Silva
Regilene Silva05/02/2024 12:17
Compartilhe

Código procedural, POO e Page Object Model para iniciantes

  • #Python
  • #POO
  • #Selenium

Observe o script:

driver = webdriver.Chrome()
driver.get("https://shopee.com.br/")

try:
  cookie_button = WebDriverWait(driver, 10).until(
      EC.element_to_be_clickable((By.XPATH, '//*[@id="main"]/div/div[5]/div/div[3]/button[2]'))
  )
  ActionChains(driver).click(cookie_button).perform()
except Exception as e:
  print(f"Erro ao rejeitar cookie: {e}")


WebDriverWait(driver, 10).until(
  EC.presence_of_element_located((By.XPATH, '//*[@id="main"]/div/div[2]/div/div/div/div[2]/div/div[2]/form/div[1]/div[1]/input'))
)


email_input = driver.find_element(By.XPATH, '//*[@id="main"]/div/div[2]/div/div/div/div[2]/div/div[2]/form/div[1]/div[1]/input')
email_input.clear()  # Limpar qualquer valor existente
email_input.send_keys("SEU_EMAIL")
print("Preencheu o campo de e-mail")


senha_input = driver.find_element(By.XPATH, '//*[@id="main"]/div/div[2]/div/div/div/div[2]/div/div[2]/form/div[2]/div[1]/input')
senha_input.clear()  # Limpar qualquer valor existente
senha_input.send_keys("SUA_SENHA_SECRETA")
print("Preencheu o campo de senha")


try:
  entrar_button = WebDriverWait(driver, 20).until(
      EC.element_to_be_clickable((By.XPATH, '//*[@id="main"]/div/div[2]/div/div/div/div[2]/div/div[2]/form/button'))
  )
  entrar_button.click()
  print("Clicou no botão 'Entrar'")
except Exception as e:
  print(f"Erro ao clicar no botão 'Entrar': {e}")

O código em resumo está realizando a automação de algumas ações típicas de login em uma página, como abrir a página, rejeitar cookies, esperar pela página de login carregar, preencher campos de e-mail e senha, e clicar no botão de entrada.

Agora ...

imagine quantas linhas serão acrescentadas para lidar com popups, alertas, e se a aplicação utilizar frames ou iFrames, você precisará alternar entre eles para interagir com elementos internos… acrescentar espera explícita, ou implícita para interagir com elementos, e se a página for dinâmica os elementos carregarem em tempos diferentes… esses são pequenos desafios que podem se tornar incômodos à medida que os projetos vão ficando mais complexos. Considere ainda, que, nesse pequeno script, seja necessária a colaboração de outros programadores. Vamos concordar que muita coisa pode dar errado quando acrescentamos códigos em estruturas procedurais como esta.

 Estruturas procedurais:

O primeiro script apresenta um código mais procedural, ou seja, as ações e interações são realizadas diretamente no script principal sem encapsulamento em classes e não possui métodos específicos. Nele as ações são executadas em ordem sequencial no script principal e por carecer de modularidade, torna difícil dividir o código em partes independentes e reutilizáveis. Além disso, ações e lógica de interação podem estar entrelaçadas, dificultando a compreensão e a manutenção isolada de cada parte. Atualizações ou mudanças no script podem tornar o código menos ágil, especialmente se diferentes partes do código precisarem ser manipuladas simultaneamente.

Agora observe o mesmo script com classes e métodos definidos:

class ShopeeHomePage:
  def __init__(self, driver):
      self.driver = driver

  def accept_cookie(self):
      try:
          cookie_button = WebDriverWait(self.driver, 10).until(
              EC.element_to_be_clickable((By.XPATH, '//*@id="main"]/div/div[5]/div/div[3]/button[2]'))
          )
          cookie_button.click()
      except Exception as e:
          print(f"Erro ao rejeitar cookie: {e}")


  def navigate_to_login_page(self):
      # Adicione lógica aqui para navegar para a página de login, se necessário
      pass


class LoginPage:
  def __init__(self, driver):
      self.driver = driver


  def wait_for_login_page_to_load(self):
      WebDriverWait(self.driver, 10).until(
          EC.presence_of_element_located((By.XPATH, '//*[@id="main"]/div/div[2]/div/div/div/div[2]/div/div[2]/form/div[1]/div[1]/input'))
      )


  def enter_email(self, email):
      email_input = self.driver.find_element(By.XPATH, '//*[@id="main"]/div/div[2]/div/div/div/div[2]/div/div[2]/form/div[1]/div[1]/input')
      email_input.clear()
      email_input.send_keys(email)


  def enter_password(self, password):
      senha_input = self.driver.find_element(By.XPATH, '//*[@id="main"]/div/div[2]/div/div/div/div[2]/div/div[2]/form/div[2]/div[1]/input')
      senha_input.clear()
      senha_input.send_keys(password)


  def click_login_button(self):
      try:
          entrar_button = WebDriverWait(self.driver, 20).until(
              EC.element_to_be_clickable((By.XPATH, '//*[@id="main"]/div/div[2]/div/div/div/div[2]/div/div[2]/form/button'))
          )
          entrar_button.click()
      except Exception as e:
          print(f"Erro ao clicar no botão 'Entrar': {e}")


driver = webdriver.Chrome()
driver.get("https://shopee.com.br/")

shopee_home = ShopeeHomePage(driver)
shopee_home.accept_cookie()

login_page = LoginPage(driver)
login_page.wait_for_login_page_to_load()
login_page.enter_email("SEU_EMAIL")
login_page.enter_password("SUA_SENHA_SECRETA")
login_page.click_login_button()

Ao formatar o script criando classes (que encapsulam lógicas de interação), e chamadas de métodos (que realizam ações) temos um código orientado a objetos e quando aplicado a automação de teste web, afirmamos que este é um padrão de design Page Object Model (POM).

Nessa estrutura, as classes se transformam em page objects, e ao instanciarmos uma classe (ou criar objetos de classe) criamos objetos específicos que representam a página de aplicação. No exemplo, as classes ShopeeHomePage e LoginPage são exemplos de Page Objects. No final do script, você instancia objetos das classes ShopeeHomePage e LoginPage usando shopee_home = ShopeeHomePage(driver) e login_page = LoginPage(driver).

As instancias de classe então são usadas para chamar métodos que realizam interações específicas. Elas utilizam esses objetos para interagir com a página, chamando métodos específicos dessas classes para realizar ações como aceitar cookies, esperar pela carga da página de login e realizar o login:

login_page = LoginPage(driver)
login_page.wait_for_login_page_to_load()
login_page.enter_email("SEU_EMAIL")
login_page.enter_password("SUA_SENHA_SECRETA")
login_page.click_login_button()

Essa estrutura é uma parte fundamental da programação orientada a objetos onde você interage com objetos e invoca comportamentos específicos (métodos) associados a esses objetos:

objeto.metodo ()

Agora que nós vimos a diferença entre um código procedural e orientado a objetos, e na óptica da automação orientado a Page Object Model, concordamos que essa última abordagem facilita a organização do código e promove a reutilização de código através da criação de classes e objetos. Ainda, facilita a manutenção ao relacionar atualizações às classes (page object) e a escalabilidade, ao lidar de forma eficiente com aumento na complexidade e tamanho do projeto.

Para os programadores iniciantes é necessário apenas ‘ver’ o código e executar as boas práticas de programação, que incluem várias diretrizes que visam criar código limpo, modular e reutilizável. E ainda, mais legível, fácil de entender, manter e estender. Além de colaborativo, é claro.

Espero com esse conteúdo ter contribuído para o conhecimento de quem está começando, assim como eu.

Compartilhe
Comentários (4)
Regilene Silva
Regilene Silva - 06/02/2024 08:39

Obrigada, Ronaldo! Confesso que estou montando um currículo para pré-adolescentes. Pretendo no futuro trabalha em plataforma que dê aulas para essa faixa etária, então o conteúdo e a explicação (didática) precisa ser bem clara. Fico sempre selecionando as perguntas que as crianças fariam. Obrigada novamente!

Ronaldo Schmidt
Ronaldo Schmidt - 05/02/2024 22:35

Realmente muito bom mas confesso que só vim aqui pela capa extravagante.

Mas não me arrependo!

Excelente artigo. Comecei meus estudos talvez por sorte sempre utlizando as tecnicas mencionadas.

Dividir para conquistar e ter o controle sobre o que está acontecendo é muito bom...

Obrigado por compartilhar.

Regilene Silva
Regilene Silva - 05/02/2024 21:07

O contraditório é que a pessoa olha, e vê algo tão ruim que ela tira a própria vida. kkkk Não sei se o paralelo foi bom, mas o filme é muito assustador.

Gustavo Silva
Gustavo Silva - 05/02/2024 20:20

hahaha mandou bem na capa!!!