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

  1. Der Geldtransfer sollte erfolgen, wenn auf dem Quellkonto genügend Guthaben vorhanden ist
  2. Die Überweisung sollte erfolgen, wenn die Angaben zum Zielkonto korrekt sind.
  3. Der Geldtransfer sollte stattfinden, wenn das vom Benutzer eingegebene Transaktionskennwort/RSA-Code/Sicherheitsauthentifizierung für die Transaktion korrekt ist
  4. Die Überweisung sollte auch dann erfolgen, wenn es ein Feiertag ist
  5. 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:

Projektaufbau:

  • Erstellen Sie ein neues Projekt
  • Erstellen Sie die folgende Verzeichnisstruktur:

Projektaufbau

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:

Projektaufbau

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:

Schritte zur Implementierung

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:

Ausführen der Tests

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:

Meldungen

Testbericht im HTML-Format

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