Was ist BDD-Test? Framework-Beispiel
Was sind BDD-Tests (Behavior Driven Development)?
BDD-Tests (verhaltensgesteuerte Entwicklung). ist eine Technik der agilen Softwareentwicklung und stellt eine Erweiterung von TDD, also Test Driven Development, dar. Bei BDD werden Testfälle in einer natürlichen Sprache geschrieben, die auch Nicht-Programmierer lesen können.
Wie funktioniert BDD-Testen?
Bedenken Sie, dass Sie mit der Erstellung des Moduls „Geldtransfer“ in einer Net Banking-Anwendung beauftragt sind.
Es gibt mehrere Möglichkeiten, es zu testen
- Der Geldtransfer sollte erfolgen, wenn auf dem Quellkonto genügend Guthaben vorhanden ist
- Die Überweisung sollte erfolgen, wenn die Angaben zum Zielkonto korrekt sind.
- Der Geldtransfer sollte stattfinden, wenn das vom Benutzer eingegebene Transaktionskennwort/RSA-Code/Sicherheitsauthentifizierung für die Transaktion korrekt ist
- Die Überweisung sollte auch dann erfolgen, wenn es ein Feiertag ist
- Der Geldtransfer sollte zu einem vom Kontoinhaber festgelegten Datum in der Zukunft erfolgen
Die Testszenario werden aufwändiger und komplexer, wenn wir zusätzliche Funktionen berücksichtigen, wie z. B. den Überweisungsbetrag X für ein Intervall Y Tage/Monate, das Stoppen der geplanten Überweisung, wenn der Gesamtbetrag Z erreicht, und so weiter
Die allgemeine Tendenz von Entwicklern besteht darin, Features zu entwickeln und später Testcode zu schreiben. Wie im obigen Fall deutlich wird, Testfall Die Entwicklung für diesen Fall ist komplex und der Entwickler wird Testen bis zur Veröffentlichung, dann wird er schnelle, aber ineffektive Tests durchführen.
Um dieses Problem zu lösen (Behavior Driven Development), wurde BDD konzipiert. Es vereinfacht den gesamten Testprozess für einen Entwickler
In BDD muss alles, was Sie schreiben, eingefügt werden Gegeben-Wann-Dann Schritte. Betrachten wir das gleiche Beispiel oben 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
Ist es nicht einfach zu schreiben, zu lesen und zu verstehen? Es deckt alle möglichen Testfälle für das Geldtransfermodul ab und kann leicht geändert werden, um mehr abzudecken. Außerdem ähnelt es eher dem Schreiben von Dokumentationen für das Geldtransfermodul.
Was ist REST-API-Testen?
Da REST heutzutage zu einem recht beliebten Stil für die Erstellung von APIs geworden ist, ist es ebenso wichtig geworden, REST-API-Testfälle zusammen mit UI-Testfällen zu automatisieren. Also im Grunde genommen sind es diese REST API-Tests beinhaltet das Testen von CRUD-Aktionen (Create-Read-Update-Delete) mit den Methoden POST, GET, PUT bzw. DELETE.
Was ist Verhalten?
Behave ist eine der beliebtesten Python BDD-Testframeworks.
Mal sehen, wie Behave funktioniert:
Feature-Dateien werden von Ihrem Business-Analysten/Sponsor oder wer auch immer mit Ihren Verhaltensszenarien geschrieben. Es verfügt über ein natürliches Sprachformat, das ein Merkmal oder einen Teil eines Merkmals mit repräsentativen Beispielen für erwartete Ergebnisse beschreibt
Diese Szenarioschritte werden mit eingeschriebenen Schrittimplementierungen abgebildet Python.
Und optional gibt es einige Umgebungskontrollen (Code, der vor und nach Schritten, Szenarien, Funktionen oder dem gesamten Schießspiel ausgeführt wird).
Beginnen wir mit der Einrichtung unseres Automatisierungstest-Frameworks mit Behave:
Einrichten des BDD-Test-Frameworks. Verhalten Sie sich weiter Windows
Installation:
- Lade und installiere Python 3 aus https://www.python.org/
- Führen Sie den folgenden Befehl in der Eingabeaufforderung aus, um behave zu installieren
- pip install verhält sich
- IDE: Ich habe PyCharm Community Edition verwendet https://www.jetbrains.com/pycharm/download
Projektaufbau:
- Erstellen Sie ein neues Projekt
- Erstellen Sie die folgende Verzeichnisstruktur:
Feature-Dateien:
Lassen Sie uns also unsere Feature-Datei erstellen Sample_REST_API_Testing.feature mit der Funktion „Durchführen von CRUD-Operationen am Dienst ‚Posts‘“.
In unserem Beispiel habe ich verwendet http://jsonplaceholder.typicode.com/ veröffentlicht einen Beispiel-REST-Dienst.
Beispiel-POST-Szenario
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
Ebenso können Sie die restlichen Szenarien wie folgt schreiben:
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."
Schritte zur Implementierung
Für die in den obigen Szenarien verwendeten Feature-Schritte können Sie Implementierungen in Python Dateien im Verzeichnis „steps“.
Das Behave-Framework identifiziert die Step-Funktion durch Dekoratoren, die mit dem Feature-Datei-Prädikat übereinstimmen. Beispielsweise sucht das gegebene Prädikat in einem Feature-Datei-Szenario nach einer Schrittfunktion mit dem Dekorator „given“. Ein ähnlicher Abgleich erfolgt für „When“ und „Then“. Aber im Fall von „Aber“, „Und“ verwendet die Step-Funktion den gleichen Dekorator wie der vorhergehende Schritt. Wenn beispielsweise „Und“ für „Gegeben“ steht, ist der passende Dekorator für die Schrittfunktion @given.
Wenn der Schritt für POST beispielsweise wie folgt implementiert werden kann:
@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
Ebenso sieht die Implementierung anderer Schritte in der Step-Python-Datei so aus:
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
Ausführen der Tests
Jetzt sind wir mit unserem Testskript-Entwicklungsteil fertig, also führen wir unsere Tests durch:
Führen Sie den folgenden Befehl in der Eingabeaufforderung aus, um unsere Feature-Datei auszuführen
C:\Programme\Python\Python37>benimm dich -f hübsch C:\ \features\feature_files_folder\Sample_REST_API_Testing.feature
Dadurch werden die Testausführungsergebnisse wie folgt angezeigt:
Berichtsanzeige auf der Konsole
Sehen wir uns hier noch eine weitere coole Sache an.
Da Benutzer Testergebnisse immer lieber in einem besser lesbaren und präsentablen Format sehen möchten, erstellen wir mithilfe von Allure Berichte im HTML-Format.
Meldungen
Zuerst müssen Sie den Allure Behave-Formatierer installieren [https://docs.qameta.io/allure-report/]:
Und nun führen Sie den folgenden Befehl aus:
Für Berichte
>benimm dich -f json -o Sample_REST_API_Testing.feature
> Reiz servieren
Dadurch wird Ihr Testergebnisbericht in einem vorzeigbaren und informativen Format wie folgt erstellt:
Testbericht im HTML-Format
Testbericht mit Anzeige der einzelnen Szenarioergebnisse
Zusammenfassung
- BDD ist verhaltensgesteuerte Entwicklung. Es handelt sich um eine der Techniken der agilen Softwareentwicklung.
- REST hat sich heutzutage zu einem recht beliebten Stil zum Erstellen von APIs entwickelt. Es ist ebenso wichtig geworden, REST-API-Testfälle zusammen mit UI-Testfällen zu automatisieren.
- BDD verfügt über ein natürliches Sprachformat, das ein Feature oder einen Teil eines Features mit repräsentativen Beispielen für erwartete Ergebnisse beschreibt
- Das Behave-Framework identifiziert die Step-Funktion durch Dekoratoren, die mit dem Feature-Datei-Prädikat übereinstimmen
- Beispiele für BDD-Testframeworks: 1) Cucumber 2) SpecFlow 3) Quantum 4) JBehave 5) Codeception