Loading repository data…
Loading repository data…
andreinaoliveira / repository
Base para automação de testes utilizando a linguagem Python com as tecnologias do Selenium Webdriver e Unittest e com a estrutura organizacional MTC (Model-Test-Controller).
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
Base para automação de testes utilizando a linguagem Python com as tecnologias do Selenium WebDriver e UnitTest e com a estrutura organizacional CMT (Controller Model Test), uma adaptação do MVC.
Para exemplificar o funcionamento da base será automatizado a tela de login do site Netflix. para cobrir os seguintes cenários de teste:
Projeto
git clone https://github.com/andreinaoliveira/QA-Base-Automation.git
Dependencias
Módulos
Os módulos devem ser instalados no cmd com os comandos abaixos
pip install selenium
pip install webdriver-manager
Contem a função titleTest() recebendo testName. Quando a função é chamada imprime o nome do teste passado por parâmetro de forma mais amigável no terminal. Essa função é chamada para cada teste do unittest localizados na pasta test.
def titleTest(testName):
print(100 * '-')
print(testName.center(100))
print(100 * '-')
Exemplo da impressão:
----------------------------------------------------------------------------------------------------
CT01 - Acessar tela de Boas Vindas
----------------------------------------------------------------------------------------------------
Importa a biblioteca de loggin e formata a mensagem de log. Nesse arquivo é criado as funções debug(), info() e error(). Cada função recebe a mensagem que será enviada como log. Essas funções são chamadas em controller/webdriver.
import logging
log_format = '%(asctime)s :: %(name)s :: %(levelname)s :: %(module)s :: %(message)s'
logging.basicConfig(format=log_format, level=logging.INFO, filemode='w')
def degub(message):
logging.debug(message)
def info(message):
logging.info(message)
def error(message):
logging.error(message)
Em webdriver.py é criada a classe Element com os seguintes atribuitos e importações:
import os
import sys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from controller import log
class Element:
def __init__(self, driver, name):
self.driver = driver
self.name = name
self.element = None
self.as_1_ID = None
self.as_2_CLASS_NAME = None
self.as_3_NAME = None
self.as_4_TAG_NAME = None
self.as_5_LINK_TEXT = None
self.as_6_PARTIAL_LINK_TEXT = None
self.as_7_CSS_SELECTOR = None
self.as_8_XPATH = None
As funções da classe ao serem chamadas (find, click e set), executará as ações e retornará [True] ou [False] de acordo com o sucesso ou não da atividade. Portanto, além de executar a ação você poderá comparar o resultado, por exemplo, checar se retornou True, ou seja, checar se a ação foi executada com sucesso.
A função é chamada na função anterior, find(). Recebe um valor inteiro na variável code, o valor está no range de 1 a 8 e se refere ao tipo de referência do elemento (id, class etc.) o código é o mesmo do atributo as_Code_Type da classe. Exemplo, instanciando a classe como as_1_ID o code da função deve ser _ code(1) para buscar por ID. O ideal é que a função seja chamada apenas pelo find(), nunca diretamente.
def _code(self, code):
if code == 1:
self.element = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.ID, self.as_1_ID))
)
elif code == 2:
self.element = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, self.as_2_CLASS_NAME))
)
elif code == 3:
self.element = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.NAME, self.as_3_NAME))
)
elif code == 4:
self.element = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.TAG_NAME, self.as_4_TAG_NAME))
)
elif code == 5:
self.element = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.LINK_TEXT, self.as_5_LINK_TEXT))
)
elif code == 6:
self.element = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, self.as_6_PARTIAL_LINK_TEXT))
)
elif code == 7:
self.element = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, self.as_7_CSS_SELECTOR))
)
elif code == 8:
self.element = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.XPATH, self.as_8_XPATH))
)
else:
log.error('Código informado em find() fora do range ou inválido.')
os.system("pause")
sys.exit()
def find(self, code):
try:
log.degub('Buscando ' + self.name)
self._code(code)
except Exception as e:
log.error('Erro ao identificar ' + self.name)
return False
else:
log.info(self.name + ' Identificado(a)')
return True
def click(self, code):
Element.find(self, code)
try:
self.element.click()
except Exception as e:
log.error('Erro ao clicar em ' + self.name)
return False
else:
log.info(self.name + ' Clicado(a)')
return True
def set(self, code, info):
Element.find(self, code)
try:
self.element.send_keys(info)
except Exception as e:
log.error('Erro ao escerver ' + self.name)
return False
else:
log.info(self.name + ' Inserido(a)')
return True
Modelo armazena todas as páginas de um sistema web em aquivos .py diferentes. Cada arquivo possui uma classe que se refere a página web em questão. O ideal é que os principais elementos da página sejam instanciados nessa classe herdando da classe Element de controller/webdriver. Para exemplificar, criamos o modelo da página de login da Netflix (login.py)
Como atribuito possuir:
As funções da página são divididas em:
def check_page_welcome(self):
e = Element(self.driver, '[Welcome] Page')
e.as_2_CLASS_NAME = 'our-story-card-title'
return e.find(2)
def click_signin_welcome(self):
e = Element(self.driver, '[Welcome] Sign In button')
e.as_5_LINK_TEXT = 'Sign In'
return e.click(5)
def set_email(self, email_or_number):
e = Element(self.driver, '[Login] Email')
e.as_1_ID = 'id_userLoginId'
return e.set(1, email_or_number)
Onde os testes de fato irão ocorrer. Após controller ser escrito suportando as instancias da página em model chega a hora de criar os casos de teste, para isso, será utilizado UnitTest. O teste será feiro com base no modelo login.py, portanto, o teste será chamado test_login.py
Como base para o teste, será importado:
from selenium import webdriver
from controller import format
from model import P01_Login
import unittest
Por padrão o unitTest possui as funções setUp e tearDown, elas são chamadas para cada função de teste criada na classe test do unittest. setUp é chamada antes do teste e tearDown após o teste. Para o projeto, essas duas funções foram programadas para: