Índice
- Setup Inicial
3.1 Introdução
3.2 Clone o Projeto
3.3 Configurando o Pytest-BDD
3.4 Pastas
- Gherkin
4.1 Declaração de Parâmetros em arquivos “.feature”
4.2 Implementando os Cenários Gherkin
- Step Definition
5.1 Scenarios VS Scenario
5.2 Declaração de Parâmetros no “Step Definition”
5.3 Implementando o “Step Definition”
1. Agradecimentos
- Esse guia foi feito com base no curso “Behavior Driven Python with pytest-bdd” por Andrew Knight.
- Curso disponível na “Testing Automation University”.
2. Pytest-BDD
Nesse tutorial utilizaremos o pytest-bdd.
O pytest-bdd é um plugin para o pytest.
Sendo um dos melhores e mais populares frameworks de teste em python, pytest também vem com vários outros plugins, tais como:
- Pytest-cov (Para cobertura de código).
- Pytest-html (Para relatórios html).
- Pytest-xdist (Para execução em paralelo).
3. Setup Inicial
3.1 Introdução
Para esse tutorial você irá precisar de conhecimento prévio que foi visto neste tutorial feito com python, selenium e pytest.
3.2 Clone o Projecto
Continuaremos a partir de um projeto de automação anterior “Escalando Testes com Docker e Python”.
Certifique-se de clonar a “branch” correta para que possamos começar: “tutorial/scale-tests-docker”.
Depois de cloná-lo, verifique no VSCode se você clonou a branch correta.
3.3 Configurando o Pytest-BDD
Utilize o pipenv para criar um ambiente virtual para o projeto e para gerenciar suas dependências.
Abra a raiz do projeto no seu “Prompt de Comando”.
E execute o comando abaixo.
pipenv install
O comando de instalação pipenv irá instalar todos os pacotes de dependência especificados no arquivo “Pipfile”.
Utilize pipenv para instalar mais um pacote de dependência que iremos utilizar neste tutorial.
pipenv install pytest-bdd
Após ter instalado o pytest-bdd você pode verificar que ele foi adicionado no arquivo “Pipfile” e “Pipfile.lock”.
“Pipfile”:
“Pipfile.lock”:
3.4 Pastas
Crie as pastas “features” e “step_defs” dentro de “tests” no seu projeto.
- A pasta “features” é onde os cenários gherkin estão localizados.
- A pasta “step_defs” é onde todos os módulos python, inclusive o conftest e os códigos dos “the step definition” estão localizados.
- O “step definition” é a implementação para cada uma das linhas de gherkin.
4. Gherkin
Primeiro você precisa mapear e depois escrever nos arquivos “.feature” os cenários gherkin que você planejou.
Apenas após ter os cenários é que você deveria implementar o “step_definition”.
4.1 Declaração de Parâmetros em arquivos “.feature”
A declaração de parâmetros é feita utilizando aspas duplas, ex:
When the user searches for "panda"
Os parâmetros do “scenario outline” são declarados entre <>, ex:
When the user searches for <name>
Um parâmetro escrito em múltiplas linhas deve ser declarado entre aspas triplas, ex:
When the user searches for the phrase:
"""
Line1,
Line2,
Line3.
"""
4.2 Implementando os Cenários Gherkin
No arquivo “.feature” abaixo você pode ver uma estrutura normal de um arquivo gherkin.
Ele possui três cenários de teste:
- O primeiro é um cenário normal recebendo um parâmetro e verificando os resultados.
- O segundo é um “scenario outline”.
- O terceiro é um cenário normal com parâmetros de várias linhas.
O “background” funciona quase como uma função “setup”, ele é executado antes de cada cenário.
“web.feature”:
Feature: DuckDuckGo Web Browsing
As a web surfer,
I want to find information online,
So I can learn new things and get tasks done.
Background:
Given the DuckDuckGo home page is displayed
Scenario: Basic DuckDuckGo Result Title
When the user searches for "panda"
Then results title contains "panda"
Scenario Outline: Basic DuckDuckGo Search
When the user searches for <name>
Then results are shown for <found_animal>
Examples: Animals
| name | found_animal |
| panda | panda |
| python | python |
| polar bear | polar bear |
Scenario: Lengthy DuckDuckGo Search
When the user searches for the phrase:
"""
When in the Course of human events, it becomes necessary for one people
to dissolve the political bands which have connected them with another,
and to assume among the powers of the earth, the separate and equal
station to which the Laws of Nature and of Nature's God entitle them,
a decent respect to the opinions of mankind requires that they should
declare the causes which impel them to the separation.
"""
Then one of the results contains "Declaration of Independence"
5. Step Definition
5.1 Scenarios VS Scenario
Dentro de um arquivo “step definition” você precisa declarar qual “.feature” será implementada.
Existem duas opções.
- Primeira opção.
Declarando e implementando os cenários individualmente no “step definition”.
from pytest_bdd import scenario
@scenario('../features/web.feature', "Basic DuckDuckGo Search")
def test_scenario_basic_search():
pass
@scenario('../features/web.feature', "Lengthy DuckDuckGo Search")
def test_scenario_lengthy_search():
pass
Obs.: Os nomes das funções dos cenários devem começar com “test_”.
- Segunda Opção (A opção que iremos utilizar neste tutorial).
A forma otimizada de declarar e implementar cenários é utilizando “scenarios” ao invés de “@scenario”.
Um dos pontos positivos é que não é necessário implementar a função “def”.
from pytest_bdd import scenarios
scenarios('../features/web.feature')
5.2 Declaração de Parâmetros no “Step Definition”
O parâmetro com aspas duplas deveria ser declarado como abaixo.
@when(parsers.parse('the user searches for "{parameter}"'))
O “scenario outline” e os parâmetros multi linhas (que utilizam aspas triplas) devem ser declaradas como abaixo, sem as aspas.
@when(parsers.parse('the user searches for {parameter}'))
5.3 Implementando o “Step Definition”
O código abaixo mostra que é possível que um “step definition” possa ser utilizado por mais de um cenário gherkin.
from pytest_bdd import scenarios, given, when, then, parsers
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from pages.search import DuckDuckGoSearchPage
from pages.result import DuckDuckGoResultPage
scenarios('../features/web.feature')
@given('the DuckDuckGo home page is displayed')
def duckduckgo_home(browser):
DuckDuckGoSearchPage(browser).load()
pass
@when(parsers.parse('the user searches for "{text}"'))
@when(parsers.parse('the user searches for {text}'))
@when(parsers.parse('the user searches for the phrase:\n{text}'))
def search_phrase(browser, text):
DuckDuckGoSearchPage(browser).search(text)
@then(parsers.parse('results title contains "{phrase}"'))
def search_results_title(browser, phrase):
assert WebDriverWait(browser, 5).until(EC.title_contains(phrase))
@then(parsers.parse('results are shown for {phrase}'))
def results_have_one(browser, phrase):
results = DuckDuckGoResultPage(browser).result_link_titles()
assert len(results) > 0
assert DuckDuckGoResultPage(browser).search_input_value() == phrase
@then(parsers.parse('one of the results contains "{phrase}"'))
def search_results(browser, phrase):
results = DuckDuckGoResultPage(browser).result_link_titles()
assert any(phrase in s for s in results)
6. Outras Alterações
Caso queira ver os testes em execução, altere o arquivo “config.json” para executar localmente.
“config.json”:
{
"browser": "Chrome",
"type": "local",
"implicit_wait": 10,
"url_remote": "http://127.0.0.1:4444/wd/hub"
}
Obs.: Para executar seus testes lembre-se de verificar se o seu chromedriver ou geckodriver estão na mesma versão que os navegadores instalados na sua máquina.
Aqui segue um tutorial de como instalar webdrivers na sua máquina.
7. Executando os Testes
O comando para executar os testes é o mesmo utilizado nos tutoriais anteriores.
pipenv run python -m pytest
8. Repositório
Criei uma branch nova para esse tutorial chamada “tutorial/gherkin-pytest-bdd”, clique no link abaixo para visualizar:
https://github.com/LuizGustavoR/intro-selenium-py/tree/tutorial/gherkin-pytest-bdd
Fim.