O que é teste BDD? Exemplo de estrutura

O que são testes BDD (Desenvolvimento Orientado a Comportamento)?

Teste BDD (desenvolvimento orientado a comportamento) é uma técnica de desenvolvimento ágil de software e é uma extensão do TDD, ou seja, Test Driven Development. No BDD, os casos de teste são escritos em uma linguagem natural que até mesmo não-programadores podem ler.

Como funciona o teste BDD?

Considere que você foi designado para criar o módulo de transferência de fundos em um aplicativo do Net Banking.

Existem várias maneiras de testá-lo

  1. A transferência de fundos deverá ocorrer se houver saldo suficiente na conta de origem
  2. A transferência de fundos deve ocorrer se os detalhes do ar-condicionado de destino estiverem corretos
  3. A transferência de fundos deverá ocorrer se a senha da transação/código RSA/autenticação de segurança da transação inserida pelo usuário estiver correta
  4. A transferência de fundos deve ocorrer mesmo em feriado bancário
  5. A transferência de fundos deverá ocorrer em data futura definida pelo titular da conta

A Cenário de Teste tornam-se mais elaborados e complexos à medida que consideramos recursos adicionais, como transferir o valor X por um intervalo Y dias/meses, interromper a transferência programada quando o valor total atingir Z e assim por diante

A tendência geral dos desenvolvedores é desenvolver recursos e escrever código de teste posteriormente. Como, evidente no caso acima, Caso de teste o desenvolvimento para este caso é complexo e o desenvolvedor irá adiar Ensaios até o lançamento, momento em que ele fará testes rápidos, mas ineficazes.

Para superar esse problema (Behavior Driven Development) o BDD foi concebido. Facilita todo o processo de teste para um desenvolvedor

No BDD, tudo o que você escreve deve entrar Dado-Quando-Então passos. Vamos considerar o mesmo exemplo acima no BDD

Given that a fund transfer module in net banking application has been developed
And I am accessing it with proper authentication
WhenI shall transfer with enough balance in my source account
Or I shall transfer on a Bank Holiday
Or I shall transfer on a future date
And destination a/c details are correct
And transaction password/rsa code / security authentication for the transaction is correct
And press or click send button
Then amount must be transferred
And the event will be logged in log file

Não é fácil escrever, ler e entender? Abrange todos os casos de teste possíveis para o módulo de transferência de fundos e pode ser facilmente modificado para acomodar mais. Além disso, é mais como escrever documentação para o módulo de transferência de fundos.

O que é teste de API REST?

Como REST se tornou um estilo bastante popular para construção de APIs hoje em dia, tornou-se igualmente importante automatizar casos de teste de API REST junto com casos de teste de UI. Então, basicamente, esses REST Teste de API envolve testes de ações CRUD (Create-Read-Update-Delete) com métodos POST, GET, PUT e DELETE respectivamente.

O que é Comportar-se?

Comportar-se é um dos populares Python Estruturas de teste BDD.

Vamos ver como o Behave funciona:

Os arquivos de recursos são escritos por seu analista de negócios/patrocinador/quem quer que contenha seus cenários de comportamento. Possui um formato de linguagem natural que descreve um recurso ou parte de um recurso com exemplos representativos dos resultados esperados

Essas etapas do cenário são mapeadas com implementações de etapas escritas em Python.

E opcionalmente, existem alguns controles ambientais (código para rodar antes e depois das etapas, cenários, recursos ou toda a partida de tiro).

Vamos começar com a configuração de nossa estrutura de teste de automação com Behave:

Configurando o BDD Testing Framework Comporte-se Windows

Instalação:

Configuração do projeto:

  • Crie um novo projeto
  • Crie a seguinte estrutura de diretórios:

Configuração do Projeto

Arquivos de recursos:

Então, vamos construir nosso arquivo de recursos Sample_REST_API_Testing.feature tendo como recurso a realização de operações CRUD no serviço de 'postagens'.

Em nosso exemplo, usei http://jsonplaceholder.typicode.com/ publica exemplo de serviço REST.

Exemplo de cenário POST

Scenario: POST post example ->Here we are considering creating new post item using 'posts' service
Given: I set post posts API endpoint ->This is prerequisite for the test which is setting URL of posts service
When: I set HEADER param request content type as "application/json."
And set request body
And send POST HTTP request ->This is actual test step of sending a post request
Then: Then I receive valid HTPP response code 201 
And Response body "POST" is non-empty-> This is verification of response body	

Da mesma forma, você pode escrever os cenários restantes da seguinte forma:

Configuração do Projeto

Sample_REST_API_Testing.feature

Feature: Test CRUD methods in Sample REST API testing framework

Background:
	Given I set sample REST API url

Scenario: POST post example
  Given I Set POST posts api endpoint
 When I Set HEADER param request content type as "application/json." 
    And Set request Body
 And Send a POST HTTP request 
 Then I receive valid HTTP response code 201
    And Response BODY "POST" is non-empty. 


Scenario: GET posts example
  Given I Set GET posts api endpoint "1"
  When I Set HEADER param request content type as "application/json." 
	And Send GET HTTP request
  Then I receive valid HTTP response code 200 for "GET." 
	And Response BODY "GET" is non-empty


Scenario: UPDATE posts example
  Given I Set PUT posts api endpoint for "1"
  When I Set Update request Body
	And Send PUT HTTP request
  Then I receive valid HTTP response code 200 for "PUT." 
	And Response BODY "PUT" is non-empty


Scenario: DELETE posts example
  Given I Set DELETE posts api endpoint for "1"
  When I Send DELETE HTTP request
  Then I receive valid HTTP response code 200 for "DELETE." 

Implementação de etapas

Agora, para as etapas de recursos usadas nos cenários acima, você pode escrever implementações em Python arquivos no diretório “etapas”.

A estrutura Behave identifica a função Step pelos decoradores que correspondem ao predicado do arquivo de recursos. Por exemplo, o predicado dado no cenário do arquivo de recurso procura a função de etapa com o decorador “dado”. Correspondência semelhante acontece para When e Then. Mas no caso de 'Mas', 'E', a função Step leva o decorador da mesma forma que a etapa anterior. Por exemplo, se 'E' vier para Dado, o decorador da função de etapa correspondente será @dado.

Por exemplo, a etapa When para POST pode ser implementada da seguinte forma:

@when (u'I Set HEADER param request content type as "{header_conent_type}"')
Mapping of When, here notice “application/json” is been passed from feature file for "{header_conent_type}” . This is called as parameterization


def step_impl (context, header_conent_type):
This is step implementation method signature

request_headers['Content-Type'] = header_conent_type
Step implementation code, here you will be setting content type for request header

Da mesma forma, a implementação de outras etapas no arquivo step python será semelhante a esta:

Implementação de etapas

sample_step_implementation.py

from behave import given, when, then, step
import requests

api_endpoints = {}
request_headers = {}
response_codes ={}
response_texts={}
request_bodies = {}
api_url=None

@given(u'I set sample REST API url')
def step_impl(context):
    global api_url
    api_url = 'http://jsonplaceholder.typicode.com'

# START POST Scenario
@given(u'I Set POST posts api endpoint')
def step_impl(context):
    api_endpoints['POST_URL'] = api_url+'/posts'
    print('url :'+api_endpoints['POST_URL'])

@when(u'I Set HEADER param request content type as "{header_conent_type}"')
def step_impl(context, header_conent_type):
    request_headers['Content-Type'] = header_conent_type

#You may also include "And" or "But" as a step - these are renamed by behave to take the name of their preceding step, so:
@when(u'Set request Body')
def step_impl(context):
    request_bodies['POST']={"title": "foo","body": "bar","userId": "1"}

#You may also include "And" or "But" as a step - these are renamed by behave to take the name of their preceding step, so:
@when(u'Send POST HTTP request')
def step_impl(context):
    # sending get request and saving response as response object
    response = requests.post(url=api_endpoints['POST_URL'], json=request_bodies['POST'], headers=request_headers)
    #response = requests.post(url=api_endpoints['POST_URL'], headers=request_headers) #https://jsonplaceholder.typicode.com/posts
    # extracting response text
    response_texts['POST']=response.text
    print("post response :"+response.text)
    # extracting response status_code
    statuscode = response.status_code
    response_codes['POST'] = statuscode

@then(u'I receive valid HTTP response code 201')
def step_impl(context):
    print('Post rep code ;'+str(response_codes['POST']))
    assert response_codes['POST'] is 201
# END POST Scenario

# START GET Scenario
@given(u'I Set GET posts api endpoint "{id}"')
def step_impl(context,id):
    api_endpoints['GET_URL'] = api_url+'/posts/'+id
    print('url :'+api_endpoints['GET_URL'])

#You may also include "And" or "But" as a step - these are renamed by behave to take the name of their preceding step, so:
@when(u'Send GET HTTP request')
def step_impl(context):
    # sending get request and saving response as response object
    response = requests.get(url=api_endpoints['GET_URL'], headers=request_headers) #https://jsonplaceholder.typicode.com/posts
    # extracting response text
    response_texts['GET']=response.text
    # extracting response status_code
    statuscode = response.status_code
    response_codes['GET'] = statuscode

@then(u'I receive valid HTTP response code 200 for "{request_name}"')
def step_impl(context,request_name):
    print('Get rep code for '+request_name+':'+ str(response_codes[request_name]))
    assert response_codes[request_name] is 200

@then(u'Response BODY "{request_name}" is non-empty')
def step_impl(context,request_name):
    print('request_name: '+request_name)
    print(response_texts)
    assert response_texts[request_name] is not None
# END GET Scenario

#START PUT/UPDATE
@given(u'I Set PUT posts api endpoint for "{id}"')
def step_impl(context,id):
    api_endpoints['PUT_URL'] = api_url + '/posts/'+id
    print('url :' + api_endpoints['PUT_URL'])

@when(u'I Set Update request Body')
def step_impl(context):
    request_bodies['PUT']={"title": "foo","body": "bar","userId": "1","id": "1"}

@when(u'Send PUT HTTP request')
def step_impl(context):
    # sending get request and saving response as response object  # response = requests.post(url=api_endpoints['POST_URL'], headers=request_headers) #https://jsonplaceholder.typicode.com/posts
    response = requests.put(url=api_endpoints['PUT_URL'], json=request_bodies['PUT'], headers=request_headers)
    # extracting response text
    response_texts['PUT'] = response.text
    print("update response :" + response.text)
    # extracting response status_code
    statuscode = response.status_code
    response_codes['PUT'] = statuscode
#END PUT/UPDATE

#START DELETE
@given(u'I Set DELETE posts api endpoint for "{id}"')
def step_impl(context,id):
    api_endpoints['DELETE_URL'] = api_url + '/posts/'+id
    print('url :' + api_endpoints['DELETE_URL'])

@when(u'I Send DELETE HTTP request')
def step_impl(context):
    # sending get request and saving response as response object
    response = requests.delete(url=api_endpoints['DELETE_URL'])
    # response = requests.post(url=api_endpoints['POST_URL'], headers=request_headers) #https://jsonplaceholder.typicode.com/posts
    # extracting response text
    response_texts['DELETE'] = response.text
    print("DELETE response :" + response.text)
    # extracting response status_code
    statuscode = response.status_code
    response_codes['DELETE'] = statuscode
#END DELETE

Executando os testes

Agora, concluímos nossa parte de desenvolvimento do script de teste, então vamos executar nossos testes:

Execute o seguinte comando no prompt de comando para executar nosso arquivo de recurso

C:\Programas\Python\Python37>comporte-se -f bonito C:\ \features\feature_files_folder\Sample_REST_API_Testing.feature

Isso exibirá os resultados da execução do teste da seguinte forma:

Executando os testes

Exibição de relatório no console

Vamos ver mais uma coisa legal aqui.

Como os usuários sempre preferem ver os resultados dos testes em um formato mais legível e apresentável, vamos ter relatórios em formato HTML com a ajuda do Allure.

Relatórios

Primeiro, você precisa instalar o formatador Allure Behave [https://docs.qameta.io/allure-report/]:

E agora execute o seguinte comando:

Para relatórios

>comporte-se -f json -o Sample_REST_API_Testing.feature

> servir fascínio

Isso irá gerar seu relatório de resultados de teste no formato apresentável e informativo como este:

Relatórios

Relatório de teste em formato HTML

Relatório de teste em formato HTML

Relatório de teste exibindo o resultado do cenário individual

Resumo

  • BDD é desenvolvimento orientado por comportamento. É uma das técnicas de desenvolvimento ágil de software.
  • REST se tornou um estilo bastante popular para construção de APIs hoje em dia. Tornou-se igualmente importante automatizar casos de teste de API REST junto com casos de teste de UI.
  • O BDD possui um formato de linguagem natural que descreve um recurso ou parte de um recurso com exemplos representativos dos resultados esperados
  • A estrutura Behave identifica a função Step pelos decoradores que correspondem ao predicado do arquivo de recursos
  • Exemplos de estruturas de teste BDD: 1) Cucumber 2) SpecFlow 3) Quantum 4) JBehave 5) Codecepção