Gerando relatórios de testes automatizados com Selenium em Python

O início

Comecei a me aventurar no mundo dos testes automatizados logo quando iniciei a minha carreira de QA, foi um colega que me mostrou de que forma poderíamos automatizar alguns processos e testes no sistema web que a empresa desenvolvia utilizando Selenium, naquele tempo, eu já possuía um bom conhecimento em Java, porém, o colega me apresentou o Selenium utilizando a linguagem Python, desde então adotei o Python para desenvolver os scripts de teste com Selenium, embora também saiba automatizar utilizando Java com Junit ou TetsNG.

No que vem a seguir, mostro como, fazendo o uso do Pytest e seus Plugins, podemos gerar relatórios dos testes automatizados.
O código de exemplo foi escrito usando a extensão selenium IDE com o framwork Unittest, ou seja, foram escritos de forma que qualquer pessoa que conheça o básico de Selenium e Python possa entender e reproduzir sem complicações, deixando um pouco de lado questões como padrões de desenvolvimento e boas práticas no desenvolvimento de testes automatizados (Mais sobre boas práticas pode ser lido clicando aqui).

O problema dos relatórios

Opto por desenvolver meus testes em Python por vários motivos, contudo, sempre houve algo que me incomodava, nos casos de testes escritos em Java por exemplo, o próprio framwork de teste unitário TestNG, oferecia ao fim da execução dos testes um relatório da execução, o qual ajuda muito, na análise e solução de problemas nos scripts e erros no teste, porém, em Python, usando o Unittest eu não tinha esse recurso.

Pytest

Após alguma pesquisa acabei descobrindo o Pytest, o Pytest é um framwork que auxila a escrever, organizar e rodar os testes no Python.(Clique aqui para saber mais sobre o Pytest).
Embora o Pytest não possua nativamente a funcionalidade de gerar relatórios dos testes, ele possuí uma infinidade de plugins que facilitam e muito a vida de quem precisa escrever testes automatizados e unitários (Clique aqui para ver a extensa lista de Plugins), é fazendo uso de um desses plugins que vamos gerar o relatório dos testes.
Outra vantagem do pytest é que ele dá suporte a testes escritos usando o framwork Unittest, ou seja, graças a isso não é necessário alterar os testes que foram escritos usando o unittest.

Configurando o ambiente

Antes de instalarmos o Pytest e o Plugin para gerar relatórios em html é necessário que já tenhamos instalado e configurado:

  • Python 3.x
  • Pip
  • Selenium Webdriver
  • Scripts de testes escritos em Python.

Instalando o Pytest

Para instalar o Pytest é muito simples, basta instala-lo utilizando o comando:

$ pip install pytest

Instalando o plugin pytest-html

Para instalar o pytest-html basta instala-lo utilizando o comando:

$ pip install pytest-html

Gerando relatórios

Após instalar o Pytest e o pytest-html estamos prontos para gerar relatórios dos nossos scripts de testes, nesse exemplo uso um script simples, que possui dois testes, sendo eles:

  • 1 - Busca queijo, esse teste abre acesso o google.com, pesquisa a palavra queijo, clica no resultado da WikiPédia e verifica se o título do artigo é a palavra queijo.
    def test_google_search_queijo(self):
        driver = self.driver
        driver.get(self.base_url + "/webhp?hl=pt-BR&sa=X&ved=0ahUKEwj7rOWTxp3TAhXJjpAKHTfpC2UQPAgD")
        driver.find_element_by_id("lst-ib").clear()
        driver.find_element_by_id("lst-ib").send_keys("queijo")
        driver.find_element_by_id("lst-ib").submit()
        driver.find_element_by_link_text(u"Queijo – Wikipédia, a enciclopédia livre").click()
        self.assertEqual("Queijo", driver.find_element_by_css_selector("#mw-content-text > p > b").text)
        self.assertEqual("https://pt.wikipedia.org/wiki/Queijo", driver.current_url)
  • 2 - similar ao primeiro teste este também acessa o google, pesquisa pela palavra queijo, acessa a Wikipédia, porém, ele verifica se a palavra no titulo do artigo é carne, ou seja, induzo meu script ao erro para fins de demonstração.
       def test_google_search_carne(self):
        driver = self.driver
        driver.get(self.base_url + "/webhp?hl=pt-BR&sa=X&ved=0ahUKEwj7rOWTxp3TAhXJjpAKHTfpC2UQPAgD")
        driver.find_element_by_id("lst-ib").clear()
        driver.find_element_by_id("lst-ib").send_keys("queijo")
        driver.find_element_by_id("lst-ib").submit()
        driver.find_element_by_link_text(u"Queijo – Wikipédia, a enciclopédia livre").click()
        queijo = driver.find_element_by_css_selector("#mw-content-text > p > b").text
        self.assertEqual("carne", queijo)
  • 3 - Código completo
# -*- coding: utf-8 -*-
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest
from Python.objectrepository import OpenBrowser
from selenium import webdriver

class TestGoogleSearch(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Firefox()
        self.driver.implicitly_wait(10)
        self.verificationErrors = []
        self.accept_next_alert = True
        self.driver = OpenBrowser.openBrowserFirefox(self)
        self.base_url = "https://www.google.com.br/"

    def test_google_search_queijo(self):
        driver = self.driver
        driver.get(self.base_url + "/webhp?hl=pt-BR&sa=X&ved=0ahUKEwj7rOWTxp3TAhXJjpAKHTfpC2UQPAgD")
        driver.find_element_by_id("lst-ib").clear()
        driver.find_element_by_id("lst-ib").send_keys("queijo")
        driver.find_element_by_id("lst-ib").submit()
        driver.find_element_by_link_text(u"Queijo – Wikipédia, a enciclopédia livre").click()
        self.assertEqual("Queijo", driver.find_element_by_css_selector("#mw-content-text > p > b").text)
        self.assertEqual("https://pt.wikipedia.org/wiki/Queijo", driver.current_url)

    def test_google_search_carne(self):
        driver = self.driver
        driver.get(self.base_url + "/webhp?hl=pt-BR&sa=X&ved=0ahUKEwj7rOWTxp3TAhXJjpAKHTfpC2UQPAgD")
        driver.find_element_by_id("lst-ib").clear()
        driver.find_element_by_id("lst-ib").send_keys("queijo")
        driver.find_element_by_id("lst-ib").submit()
        driver.find_element_by_link_text(u"Queijo – Wikipédia, a enciclopédia livre").click()
        queijo = driver.find_element_by_css_selector("#mw-content-text > p > b").text
        self.assertEqual("carne", queijo)

    def is_element_present(self, how, what):
        try: self.driver.find_element(by=how, value=what)
        except NoSuchElementException as e: return False
        return True
    
    def is_alert_present(self):
        try: self.driver.switch_to_alert()
        except NoAlertPresentException as e: return False
        return True
    
    def close_alert_and_get_its_text(self):
        try:
            alert = self.driver.switch_to_alert()
            alert_text = alert.text
            if self.accept_next_alert:
                alert.accept()
            else:
                alert.dismiss()
            return alert_text
        finally: self.accept_next_alert = True
    
    def tearDown(self):
        self.driver.quit()
        self.assertEqual([], self.verificationErrors)

if __name__ == "__main__":
    unittest.main()

Para que os testes rodem e seja gerado o relatório vamos executar o seguinte comando:

$ pytest --html=report.html

ps: Para que o Pytest encontre os testes, eles devem ter no inicio do nome a palavra test, no código de exemplo, o script de teste possui o nome de “test_GoogleSearchQueijo.py”, caso não queira renomear os seus testes, será necessário informar no comando do pytest qual script deve ser rodado.

Pronto, o teste rodou, como pode ser visto no print abaixo, foram rodados dois testes, um com sucesso e outro com falha, agora basta acessar a pasta onde os nossos scripts de testes estão e abrir o arquivo Report.html.

alt text

Este é o relatório que é gerado ao fim da execução dos testes, abaixo comento um pouco sobre alguns aspectos do relatório.

alt text

O relatório é divido basicamente em três blocos sendo eles:

  • 1 - Environment, aqui são listados alguns dados do ambiente que foi usado para rodar os testes.

  • 2 - Summary, aqui é apresentado um indicador de quantos testes foram rodados e em quanto tempo isso ocorreu, além disto, são exibidos seis opções de filtros sendo elas:

    • Passed: Filtrar todos os testes que rodaram com sucesso.
    • Skipped: Serve para mostrar quantos testes foram ignorados, o pytest possui um recursos chamado de Marking que permite fazer algumas marcações nos testes como por exemplo ignorar um determinado teste (Leia mais sobre clicando aqui).
    • Failed: Tem a finalidade de filtrar os testes que falharam
    • Errors: Mostra quando houverem erros no testes, isto é, erros de código ou de ambiente.
    • Unexpected passes: Informa quantos testes não foram executados.

Clicando no teste que falhou poderemos verificar o motivo da falha, é nesse aspecto que o relatório mais nos ajuda, pois temos de forma organizada e direta todo o log de eventos do nosso teste, evitando muitas vezes horas de leitura de logs imensos e dor de cabeça.alt text

Bom pessoal, é isso, espero que o que apresentei aqui seja útil, fiquem a vontade para tirar dúvidas ou dar sugestões.
Em breve estarei escrevendo um artigo de como utilizar o framwork Allure junto com Selenium para criar rela´toprios mais elaborados para os seus testes automatizados. Caso queira dar uma olhada no Allure, clica aqui e veja uma demostração dessa fantástica ferramenta.

Muito obrigado e até a próxima!

Boa, Alan! :clap:

Parabéns cara :)

Pytest é uma ferramenta sensacional…Chega dar um aperto no coração não conseguir usar ela no dia a dia por decisões burocráticas…

Fiz um ligthing talk sobre ela + factoryboy no TDC2015

Eu sempre fico me cobrando para escrever a fundo sobre ela… obrigado por ter feito isso :)

Se quiser fazer algum post colaborativo… estamos ai :)

@Leonardo-Galani e @stefanteixeira
Muito obrigado!
Realmente o Pytest é sensacional, entendo bem essa situação de não pode usar uma ferramenta bacana no trabalho devido a decisões de terceiros.
Pode deixar, assim que eu bolar algo mais completo sobre o assunto te procuro para desenvolvermos algo.

@Alan-Schveitzer Sensacional cara, parabéns :)

@Fred-Moreira
Muito obrigado Fred, parabéns pela palestra do tdc,tive o prazer de assistir e foi fantástica, espero em breve escrever sobre o pyresttest que você apresentou.

@Alan-Schveitzer Obrigado pelo feedback da palestra :) quando for usar o pyresttest e precisar de ajuda só falar

Log in to reply

Looks like your connection to Agile Testers was lost, please wait while we try to reconnect.