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
- A transferência de fundos deverá ocorrer se houver saldo suficiente na conta de origem
- A transferência de fundos deve ocorrer se os detalhes do ar-condicionado de destino estiverem corretos
- 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
- A transferência de fundos deve ocorrer mesmo em feriado bancário
- 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:
- Baixe e instale Python 3 de https://www.python.org/
- Execute o seguinte comando no prompt de comando para instalar o comportamento
- pip install se comporta
- IDE: usei o PyCharm Community Edition https://www.jetbrains.com/pycharm/download
Configuração do projeto:
- Crie um novo projeto
- Crie a seguinte estrutura de diretórios:
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:
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:
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:
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ó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