Mitä on BDD-testaus? Käyttäytymislähtöinen kehityskehys
⚡ Älykäs yhteenveto
BDD-testaus kuvaa sovelluksen käyttäytymistä selkeällä Given-When-Then-kielellä, jotta analyytikot, kehittäjät ja testaajat jakavat yhden määrittelyn. Tämä läpikäynti soveltaa tätä lähestymistapaa REST API -testaukseen Behave-menetelmällä. Python viitekehys, joka kattaa asennuksen, ominaisuustiedostot, vaiheiden toteutuksen, suorituksen ja raportoinnin.

Mitä on BDD (Behavior Driven Development) -testaus?
BDD (Behavior-driven Development) -testaus on ketterän ohjelmistokehityksen tekniikka ja TDD:n eli testivetoisen kehityksen laajennus. BDD:ssä testitapaukset kirjoitetaan luonnollisella kielellä, jota myös ei-ohjelmoijat osaavat lukea.
Kuinka BDD-testaus toimii?
Oletetaan, että sinulle on annettu tehtäväksi luoda varainsiirtomoduuli verkkopankkisovelluksessa.
Sen testaamiseen on useita tapoja:
- Rahansiirto tulisi tehdä, jos lähdetilillä on riittävästi saldoa
- Varainsiirto tulee suorittaa, jos kohteen ilmastointitiedot ovat oikein
- Rahansiirron pitäisi tapahtua, jos käyttäjän syöttämä tapahtuman salasana / RSA-koodi / turvatodennus on oikein.
- Rahansiirron tulisi tapahtua, vaikka olisi pankkipyhä
- Rahansiirron tulee tapahtua tilinhaltijan määräämänä tulevana päivänä
Testiskenaario tulee monimutkaisemmaksi ja monimutkaisemmaksi, kun otamme huomioon lisäominaisuuksia, kuten X summan siirtämisen Y päivän tai kuukauden välein, pysäytysping ajoitettu siirto, kun kokonaissumma saavuttaa Z:n, ja niin edelleen.
Kehittäjien yleinen taipumus on kehittää ominaisuuksia ja kirjoittaa testikoodi vasta myöhemmin. Kuten yllä olevasta tapauksesta käy ilmi, Testitapaus kehitys on täällä monimutkaista, joten kehittäjä lykkää Testaus julkaisuun asti, jolloin suoritetaan nopea mutta tehoton testaus.
Tämän ongelman ratkaisemiseksi kehitettiin käyttäytymislähtöinen kehitys (Behavior Driven Development, BDD). Se helpottaa koko testausprosessia kehittäjälle.
BDD:ssä kaiken, mitä kirjoitat, on mentävä sisään Annettu-Kun-Sitten vaiheet. Tarkastellaan samaa esimerkkiä yllä BDD:ssä:
Given that a fund transfer module in net banking application has been developed And I am accessing it with proper authentication 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
Tätä lomaketta on helppo kirjoittaa, lukea ja ymmärtää. Se kattaa kaikki mahdolliset varainsiirtomoduulin testitapaukset ja sitä voidaan muokata nopeasti useampien tapausten mukaiseksi. Se on myös kuin moduulin elävää dokumentaatiota. Koska BDD kehittyi TDD:stä, niiden välinen ero kannattaa selvittää ennen työkaluihin siirtymistä.
BDD vs. TDD: Keskeiset erot
Molemmat käytännöt ovat testilähtöisiä ja lyhentävät palautesilmukoita. Ne eroavat toisistaan siinä, kuka kirjoittaa testit, mitä kieltä testit käyttävät ja mitä sovelluksen tasoa ne kuvaavat.
| Aspect | TDD (testauspohjainen kehitys) | BDD (Behavior Driven Development) |
|---|---|---|
| Focus | Miten koodiyksikkö toimii sisäisesti | Miten järjestelmä toimii käyttäjän näkökulmasta |
| Kieli | Ohjelmointikielen väitteet | Luonnollisen kielen annettu-kun-niin-skenaariot |
| Pääkirjoittaja | Kehittäjä | Liiketoiminta-analyytikko, tuoteomistaja, testaaja ja kehittäjä yhdessä |
| Readable ei-ohjelmoijien toimesta | Ei | Kyllä |
| Tyypillinen laajuus | Yksikkötaso | Ominaisuus, API ja hyväksymistaso |
| Yleiset työkalut | JUnit, pytesti, NUnit | Käyttäytyä, Cucumber, SpecFlow, JBehave |
Nämä kaksi täydentävät toisiaan eivätkä kilpaile keskenään. Joukkueet yleensä pitävät TDD yksikkötason suunnittelua varten ja lisätä päälle BDD-skenaarioita kuvaamaan toimintaa, jonka sidosryhmät tosiasiallisesti hyväksyvät. Koska REST-päätepisteet sijaitsevat täsmälleen kyseisellä hyväksyntätasolla, ne sopivat luonnollisesti BDD:hen.
Mitä REST API -testaus on?
Koska RESTistä on tullut suosittu tyyli APIen rakentamiseen, REST API -testitapausten automatisoinnista käyttöliittymätestitapausten ohella on tullut yhtä tärkeää. API-testaus sisältää CRUD (Create-Read-Update-Delete) -toimintojen testaamisen POST-, GET-, PUT- ja DELETE-metodeilla.
Mikä on Behave?
Behave on yksi suosituimmista Python BDD-testauskehykset. Näin Behave-funktiot toimivat:
- Ominaisuustiedostot kirjoittaa liiketoiminta-analyytikkosi, sponsorisi tai kuka tahansa, jolle käyttäytymisskenaariot kuuluvat. Ominaisuustiedosto käyttää luonnollisen kielen muotoa, joka kuvaa ominaisuutta tai ominaisuuden osaa ja esittää edustavia esimerkkejä odotetuista tuloksista.
- Nämä skenaarion vaiheet on yhdistetty vaiheiden toteutuksiin, jotka on kirjoitettu kielellä Python.
- Valinnaisesti ympäristökontrollit suorittavat koodia ennen vaiheita, skenaarioita, ominaisuuksia tai koko suoritusta ja niiden jälkeen.
Kun kunkin tiedoston roolit on selvitetty, kehys voidaan nyt asentaa.
BDD Testing Frameworkin määrittäminen Käyttäydy Windows
Asennus:
- Lataa ja asenna Python 3 alkaen https://www.python.org/
- Asenna Behave suorittamalla seuraava komento komentokehotteessa
pip install behave- SDI: PyCharm Yhteisöversiota käytetään tässä — https://www.jetbrains.com/pycharm/download/
Projektin määritys:
- Luo uusi projekti
- Luo seuraava hakemistorakenne
Yllä olevassa kuvakaappauksessa näkyy asettelu, jonka Behave odottaa: a piirteet hakemisto, joka sisältää ominaisuustiedostot, ja sisäkkäinen vaiheet hakemisto, joka sisältää Python toteutukset. Behave löytää molemmat nimen perusteella, joten kansioiden nimien on oltava täsmälleen samat.
Ominaisuustiedostot:
Nyt rakennetaan ominaisuustiedosto Sample_REST_API_Testing.feature, ja ominaisuus on CRUD-toiminnot 'posts'-palvelussa.
Tämä esimerkki käyttää https://jsonplaceholder.typicode.com/ julkaisee esimerkki REST-palvelusta, ilmaisesta väärennetystä API:sta, joka hyväksyy kirjoituspyynnöt ja palauttaa realistisia vastauksia ilman muutosten tallentamista.
Esimerkki POST-skenaariosta
Scenario: POST post example -> creating a new post item using the 'posts' service Given I set post posts API endpoint -> prerequisite: sets the URL of the posts service When I set HEADER param request content type as "application/json" And set request body And send POST HTTP request -> the actual test step Then I receive valid HTTP response code 201 And Response body "POST" is non-empty -> verification of the response body
Vastaavasti voit kirjoittaa loput skenaariot seuraavasti:
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"
Toteutusvaiheet
Nyt voit kirjoittaa toteutuksia yllä olevissa skenaarioissa käytettyjen ominaisuusvaiheiden osalta Python tiedostot "steps"-hakemistossa.
Behave-kehys tunnistaa askelfunktion vertaamalla koristereita ominaisuustiedoston predikaattiin. Esimerkiksi Tietty predikaatti ominaisuustiedostoskenaariossa etsii askelfunktiota, joka sisältää @given sisustaja. Sama yhdistäminen tapahtuu myös Kun ja Sitten'Mutta'- ja 'Ja'-operaattorien tapauksessa askelfunktio käyttää samaa koristelijaa kuin edellinen askel. Esimerkiksi, jos 'Ja' seuraa annettua lauseketta, vastaava askelfunktion koristelija on @given.
Esimerkiksi POST-testin When-vaihe voidaan toteuttaa seuraavasti. Huomaa, miten "application/json" välitetään ominaisuustiedostosta hakasulkeissa olevaan paikkamerkkiin – tätä kutsutaan parametrisoinniksi.
# Decorator: the braced name captures a value from the feature file @when(u'I Set HEADER param request content type as "{header_content_type}"') def step_impl(context, header_content_type): # Step implementation: set the content type on the request header request_headers['Content-Type'] = header_content_type
Samoin vaiheen muiden vaiheiden toteutus Python tiedosto tulee näyttämään tältä:
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 = 'https://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_content_type}"') def step_impl(context, header_content_type): request_headers['Content-Type'] = header_content_type # "And" or "But" steps are renamed by behave to match their preceding step @when(u'Set request Body') def step_impl(context): request_bodies['POST'] = {"title": "foo", "body": "bar", "userId": "1"} @when(u'Send POST HTTP request') def step_impl(context): # send the request and save the response object response = requests.post(url=api_endpoints['POST_URL'], json=request_bodies['POST'], headers=request_headers) response_texts['POST'] = response.text print("post response :" + response.text) response_codes['POST'] = response.status_code @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'] == 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']) @when(u'Send GET HTTP request') def step_impl(context): response = requests.get(url=api_endpoints['GET_URL'], headers=request_headers) response_texts['GET'] = response.text response_codes['GET'] = response.status_code @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] == 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): response = requests.put(url=api_endpoints['PUT_URL'], json=request_bodies['PUT'], headers=request_headers) response_texts['PUT'] = response.text print("update response :" + response.text) response_codes['PUT'] = response.status_code # 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): response = requests.delete(url=api_endpoints['DELETE_URL']) response_texts['DELETE'] = response.text print("DELETE response :" + response.text) response_codes['DELETE'] = response.status_code # END DELETE
⚠️ Huomaa: Tilakoodien vertailu == sen sijaan, is asiat. is operaattori testaa objektin identiteettiä, ei yhtäsuuruutta, ja Python 3.8 ja myöhemmin nostaa Syntaksivaroitus: ”on” literaalilla kyseiselle mallille. Mikä tahansa väite, joka on kirjoitettu muodossa assert code is 201 pitäisi kirjoittaa uudelleen muotoon assert code == 201.
Testien suorittaminen
Testiskriptin kehitys on valmis, joten suoritetaan testit. Suorita seuraava komento komentokehotteessa ominaisuustiedoston suorittamiseksi:
:: Run a single feature file with the pretty formatter behave -f pretty features\feature_files_folder\Sample_REST_API_Testing.feature :: Run every feature in the project behave
Tämä näyttää testin suorituksen tulokset seuraavasti:
Raportin näyttö konsolissa
Konsolin tulostus on kätevää kehitysvaiheessa, mutta sidosryhmät yleensä suosivat luettavaa raporttia, kuten Allure tarjoaa.
Raportit
Asenna ensin Allure Behave -muotoiluohjelma ja Allure-komentorivityökalu. Muotoiluohjelma on Python paketti; komentorivityökalu on erillinen ladattava tiedosto, joka on kuvattu kohdassa Allure-raportin dokumentaatio.
:: 1. Install the formatter pip install allure-behave :: 2. Run the tests and write raw results to a folder behave -f allure_behave.formatter:AllureFormatter -o reports/allure-results features/ :: 3. Render and open the HTML report allure serve reports/allure-results
Tämä luo testitulosraportin edustuskelpoisessa ja informatiivisessa muodossa, kuten tässä:
Testiraportti HTML-muodossa
Testiraportti, joka näyttää yksittäisen skenaarion tuloksen
Toimivasta tiedostosarjasta on hyötyä vain, jos se pysyy luettavana API:n kasvaessa, ja juuri siinä ominaisuustiedostojen kurinalaisuus kannattaa.
Parhaat käytännöt Behave-ominaisuustiedostojen kirjoittamiseen
Behave-sviitti heikkenee nopeasti, kun skenaariot kuvaavat klikkauksia ja hyötykuormia käyttäytymisen sijaan. Alla olevat käytännöt pitävät ominaisuustiedostot luettavina liiketoiminnan sidosryhmille samalla kun ne säilyttävätping Ishayoiden opettaman Python insinöörien ylläpidettävä kerros.
- Kuvaile käyttäytymistä, älä toteutusta. Kirjoita ”Jos asiakkaalla on riittävä saldo”, älä ”Jos saldosarakkeen arvo on 500”. Ominaisuustiedosto kertoo, mitä järjestelmä tekee; vaiheittaisessa tiedostossa kerrotaan, miten se tarkistetaan.
- Pidä yksi toimintatapa skenaariota kohden. Skenaario, joka vaatii tilakoodin, vastauksen rungon ja tietokantarivin, on itse asiassa kolme skenaariota. Niiden jakaminen osoittaa virheet suoraan niiden syyhyn.
- Siirrä jaettu asennusohjelma taustalle. Yllä olevassa esimerkissä käytetään
Background: Given I set sample REST API urlniin että jokainen skenaario perii perusmallin URL toistamatta sitä. - Parametrisoi kopioinnin sijaan. Tuettuja paikkamerkkejä, kuten
"{request_name}"Anna yhden askelfunktion palvella GET-, PUT- ja DELETE-väitteitä, minkä vuoksi esimerkissä tarvitaan paljon vähemmän askelmääritelmiä kuin skenaarioissa. - Käytä skenaarion ääriviivoja datamuunnelmille. Kun sama käyttäytyminen on todistettava useilla syötteillä,
Examples:taulukko on selkeämpi kuin kopioidut skenaariot. - Vältä skenaarioiden välisiä riippuvuuksia. Behave ei takaa, että POST-skenaario suoritetaan ennen GET-skenaariota jokaisessa konfiguraatiossa. Jokaisen skenaarion tulisi luoda tarvitsemansa tila.
- Korvaa moduulitason globaalit arvot kontekstilla. Esimerkissä päätepisteet ja vastaukset tallennetaan moduulisanakirjoihin lyhyyden vuoksi. Tuotantoympäristöissä ne tallennetaan Behaven moduulisanastoihin.
contextobjekti, jotta tila nollautuu siististi skenaarioiden välillä. - Merkitse skenaariot valikoiville suorituksille. Tunnisteet, kuten
@smokeor@regressionsalliabehave --tags=@smoke, mikä pitää putkilinjan palautteen nopeana.
Näiden tapojen soveltaminen ensimmäisestä ominaisuustiedostosta lähtien pitää BDD-paketin arvokkaana paljon alkuperäisiä CRUD-esimerkkejä pidemmälle. Tätä lähestymistapaa laajentavat tiimit usein yhdistävät sen Cucumber JVM-projekteille tai Postman tutkivia API-tarkistuksia varten.






