Desenvolupament impulsat pel comportament (BDD) que prova una API REST amb Behave

Què és la prova BDD?

Proves de BDD (desenvolupament basat en el comportament) és una tècnica de desenvolupament de programari àgil i és com una extensió de TDD, és a dir, Test Driven Development. En BDD, els casos de prova s’escriuen en un llenguatge natural que fins i tot els no programadors poden llegir.

En aquest tutorial de BDD, veurem la prova BDD de l'API REST amb Behave i Python

Com funcionen les proves BDD?

Penseu que esteu assignat per crear un mòdul de transferència de fons en una aplicació de banca neta.

Hi ha diverses maneres de provar-lo

  1. La transferència de fons s'hauria de fer si hi ha prou saldo al compte d'origen
  2. La transferència de fons s'hauria de fer si les dades de l'a / c de destinació són correctes
  3. La transferència de fons s’hauria de fer si la contrasenya de la transacció / codi rsa / autenticació de seguretat de la transacció introduïda per l’usuari és correcta
  4. La transferència de fons s’hauria de fer fins i tot si es tracta d’un dia festiu
  5. La transferència de fons hauria de tenir lloc en una data futura, tal com estableixi el titular del compte

L’escenari de prova es fa més elaborat i complex ja que considerem funcions addicionals com la quantitat de transferència X durant un interval de dies Y / mesos, aturar la transferència del calendari quan l’import total arriba a Z, etc.

La tendència general dels desenvolupadors és desenvolupar funcions i escriure codi de prova més endavant. Com, evidentment en el cas anterior, Cas de prova el desenvolupament d’aquest cas és complex i el desenvolupador posposarà les proves fins al llançament, moment en què farà proves ràpides però ineficaços.

Per superar aquest problema (Behavior Driven Development) es va concebre BDD. Facilita tot el procés de proves per a un desenvolupador

A BDD, cal escriure qualsevol cosa que escrigueu Donat-Quan-Aleshores passos. Considerem el mateix exemple anterior a BDD

Donat que s'ha desenvolupat un mòdul de transferència de fons en aplicacions de banca neta i hi accedo amb una autenticació adequada

  When  I 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

No és fàcil escriure, llegir i entendre? Cobreix tots els casos de prova possibles per al mòdul de transferència de fons i es pot modificar fàcilment per acomodar-ne més. A més, s’assembla més a escriure documentació per al mòdul de transferència de fons.

Què és la prova REST API?

Com que REST s'ha convertit en un estil força popular per construir API ara, ha esdevingut igualment important automatitzar els casos de prova de l'API REST juntament amb els casos de prova de la IU. De manera bàsica, aquestes proves de l'API REST consisteixen a provar accions CRUD (Crear-Llegir-Actualitzar-Eliminar) amb mètodes POST, GET, PUT i DELETE respectivament.

Què és Behave?

Behave és un dels marcs de proves de Python BDD populars.

Vegem com funciona Behave:

Els fitxers de funcions els escriu el vostre analista / patrocinador empresarial / qui tingui els vostres escenaris de comportament. Té un format de llenguatge natural que descriu una característica o una part d’una característica amb exemples representatius dels resultats esperats

Aquests passos de l'escenari es mapen amb implementacions de passos escrites a Python

I, opcionalment, hi ha alguns controls ambientals (codi per executar abans i després dels passos, escenaris, funcions o tot el partit de trets).

Comencem amb la configuració del nostre marc de proves d'automatització amb Behave:

Configuració del marc de proves Behave al Windows:

Instal·lació:

Configuració del projecte:

  • Creeu un projecte nou
  • Creeu l'estructura de directori següent:

Fitxers de funcions:

Així que anem a construir el nostre fitxer de funcions Mostra_REST_API_Testing.feature amb funció com a Realització d’operacions CRUD al servei de publicacions.

En el nostre exemple, he utilitzat http://jsonplaceholder.typicode.com/ publicacions de mostra de servei REST.

Exemple d'escenari 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 

De la mateixa manera, podeu escriure la resta d’escenaris de la següent manera:

Mostra_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.' 

Implementació dels passos

Ara, per als passos de funcions utilitzats en els escenaris anteriors, podeu escriure implementacions en fitxers Python al directori 'passos'.

El marc Behave identifica la funció Step pels decoradors que coincideixen amb el predicat del fitxer de funcions. Per exemple, el predicat donat a l'escenari del fitxer de funcions cerca la funció de pas amb el 'decorador' donat. Una coincidència similar passa per quan i després. Però en el cas de 'Però', 'I', la funció Step té el decorador igual que el pas anterior. Per exemple, si 'I' ve per Donat, el decorador de funcions de pas coincidents és @ donat.

Per exemple, quan es pot implementar el pas per POST de la següent manera:

 @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 

De la mateixa manera, la implementació d'altres passos al fitxer python de passos serà així:

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 

Realització de les proves:

Ara hem acabat amb la nostra part de desenvolupament de scripts de prova, així que executem les nostres proves:

Executeu l'ordre següent a l'indicador d'ordres per executar el nostre fitxer de funcions

C: Programes Python Python37> comporta -f maco C: \ features feature_files_folder Mostra_REST_API_Testing.feature

Es mostraran els resultats de l'execució de les proves de la següent manera:

Visualització d'informes a la consola

Vegem una cosa més interessant aquí.

Com que els usuaris sempre prefereixen veure els resultats de les proves en un format més llegible i presentable, fem informes en format HTML amb l'ajuda d'Allure.

Informes

En primer lloc, heu d’instal·lar Allure Behave formatter [ https://docs.qameta.io/allure/ ]:

I ara executeu l'ordre següent:

Per a informes

> comportar -f json -o Mostra_REST_API_Testing.feature

> seduir el servei

Això generarà l'informe de resultats de la prova en un format informatiu i presentable com aquest:

Informe de prova en format HTML

Informe de prova que mostra el resultat de l'escenari individual

Resum:

  • El BDD és un desenvolupament basat en el comportament. És una de les tècniques de desenvolupament de programari àgil.
  • Actualment, REST s’ha convertit en un estil força popular per a la creació d’APIs; ha esdevingut igualment important automatitzar els casos de prova de l’API REST juntament amb els casos de prova de la IU.
  • BDD té un format de llenguatge natural que descriu una característica o una part d’una característica amb exemples representatius dels resultats esperats
  • El marc Behave identifica la funció Step pels decoradors que coincideixen amb el predicat del fitxer de funcions