Cos'è il test BDD? Esempio di quadro

Cos'è il test BDD (sviluppo comportamentale)?

Test BDD (sviluppo comportamentale). è una tecnica di sviluppo software agile e rappresenta un'estensione del TDD, ovvero Test Driven Development. In BDD, i casi di test sono scritti in un linguaggio naturale che anche i non programmatori possono leggere.

Come funziona il test BDD?

Considera che ti è stato assegnato il compito di creare il modulo Trasferimento fondi in un'applicazione Net Banking.

Esistono diversi modi per testarlo

  1. Il trasferimento dei fondi dovrebbe avvenire se è presente un saldo sufficiente nel conto di origine
  2. Il trasferimento dei fondi dovrebbe avvenire se i dettagli del conto di destinazione sono corretti
  3. Il trasferimento dei fondi dovrebbe avvenire se la password della transazione/il codice rsa/l'autenticazione di sicurezza per la transazione inserita dall'utente è corretta
  4. Il trasferimento dei fondi dovrebbe avvenire anche se si tratta di un giorno festivo
  5. Il trasferimento dei fondi dovrebbe avvenire in una data futura stabilita dal titolare del conto

Scenario di prova diventano più elaborati e complessi quando prendiamo in considerazione funzionalità aggiuntive come l'importo del trasferimento X per un intervallo di Y giorni/mesi, l'interruzione del trasferimento programmato quando l'importo totale raggiunge Z e così via

La tendenza generale degli sviluppatori è di sviluppare funzionalità e scrivere codice di test in un secondo momento. Come evidente nel caso sopra, Test Case lo sviluppo per questo caso è complesso e lo sviluppatore rimanderà Testing fino al rilascio, a quel punto farà test rapidi ma inefficaci.

Per superare questo problema (Behavior Driven Development) è stato concepito BDD. Rende l'intero processo di test semplice per uno sviluppatore

In BDD, qualunque cosa scrivi deve entrare Dato-Quando-Allora passi. Consideriamo lo stesso esempio sopra in 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

Non è facile scrivere, leggere e capire? Copre tutti i possibili casi di test per il modulo di trasferimento fondi e può essere facilmente modificato per adattarne altri. Inoltre, è più come scrivere la documentazione per il modulo di trasferimento fondi.

Cos'è il test dell'API REST?

Poiché al giorno d'oggi REST è diventato uno stile piuttosto popolare per la creazione di API, è diventato altrettanto importante automatizzare i casi di test dell'API REST insieme ai casi di test dell'interfaccia utente. Quindi, fondamentalmente, questi REST Test dell'API prevede il test delle azioni CRUD (Create-Read-Update-Delete) rispettivamente con i metodi POST, GET, PUT e DELETE.

Cos'è Comportarsi?

Comportarsi è uno dei popolari Python Strutture di test BDD.

Vediamo come funziona Behave:

I file delle funzionalità sono scritti dal tuo analista aziendale/sponsor/da chiunque contenga i tuoi scenari comportamentali. Ha un formato in linguaggio naturale che descrive una caratteristica o parte di una caratteristica con esempi rappresentativi dei risultati attesi

Questi passaggi dello scenario sono mappati con le implementazioni dei passaggi scritte Python.

E facoltativamente, ci sono alcuni controlli ambientali (codice da eseguire prima e dopo passaggi, scenari, funzionalità o l'intera partita di tiro).

Iniziamo con la configurazione del nostro framework di test di automazione con Behave:

Configurazione del framework di test BDD Comportarsi bene Windows

Installazione:

Configurazione del progetto:

  • Crea un nuovo progetto
  • Creare la seguente struttura di directory:

Impostazione del progetto

File di funzionalità:

Quindi costruiamo il nostro file di funzionalità Esempio_REST_API_Testing.feature con funzionalità come esecuzione di operazioni CRUD sul servizio "post".

Nel nostro esempio, ho usato http://jsonplaceholder.typicode.com/ pubblica il servizio REST di esempio.

Scenario POST di esempio

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	

Allo stesso modo, puoi scrivere i restanti scenari come segue:

Impostazione del progetto

Esempio_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." 

Attuazione delle fasi

Ora, per i passaggi delle funzionalità utilizzati negli scenari precedenti, puoi scrivere le implementazioni Python file nella directory "steps".

Il framework Behavior identifica la funzione Step in base ai decoratori che corrispondono al predicato del file delle funzionalità. Ad esempio, il predicato specificato nel file delle funzionalità Scenario cerca la funzione del passaggio con il decoratore "dato". Una corrispondenza simile avviene per Quando e Allora. Ma nel caso di "Ma", "E", la funzione Step accetta il decoratore come il passaggio precedente. Ad esempio, se "And" sta per Given, il decoratore della funzione di passaggio corrispondente è @given.

Ad esempio, quando il passaggio per POST può essere implementato come segue:

@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

Allo stesso modo, l'implementazione di altri passaggi nel file step python sarà simile a questa:

Attuazione delle fasi

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

Esecuzione dei test

Ora abbiamo terminato la parte di sviluppo dello script di test, quindi eseguiamo i nostri test:

Eseguire il seguente comando sul prompt dei comandi per eseguire il nostro file di funzionalità

C:\Programmi\Python\Python37>comportarsi bene C:\ \funzionalità\cartella_file_funzionalità\Esempio_REST_API_Testing.feature

Verranno visualizzati i risultati dell'esecuzione del test come segue:

Esecuzione dei test

Visualizzazione del report sulla console

Vediamo un'altra cosa interessante qui.

Poiché gli utenti preferiscono sempre vedere i risultati dei test in un formato più leggibile e presentabile, disponiamo di report in formato HTML con l'aiuto di Allure.

Report

Innanzitutto, è necessario installare il formattatore Allure Behave [https://docs.qameta.io/allure-report/]:

E ora esegui il seguente comando:

Per i rapporti

>comportarsi -f json -o Esempio_REST_API_Testing.feature

> servire il fascino

Questo genererà il rapporto sui risultati del test nel formato presentabile e informativo come questo:

Report

Rapporto di prova in formato HTML

Rapporto di prova in formato HTML

Rapporto di prova che mostra il risultato del singolo scenario

Sommario

  • BDD è sviluppo guidato dal comportamento. È una delle tecniche di sviluppo software agile.
  • Al giorno d'oggi REST è diventato uno stile piuttosto popolare per la creazione di API, è diventato altrettanto importante automatizzare i casi di test dell'API REST insieme ai casi di test dell'interfaccia utente.
  • BDD ha un formato in linguaggio naturale che descrive una caratteristica o parte di una caratteristica con esempi rappresentativi dei risultati attesi
  • Il framework Behavior identifica la funzione Step in base ai decoratori che corrispondono al predicato del file delle funzionalità
  • Esempi di framework di test BDD: 1) Cucumber 2) SpecFlow 3) Quantum 4) JBehave 5) Codeception