Viselkedésvezérelt fejlesztés

A Wikipédiából, a szabad enciklopédiából

A viselkedésvezérelt fejlesztés (behavior-driven development, BDD) egy agilis szoftverfejlesztési folyamat, amely ösztönzi az együttműködést a fejlesztők, a QA és a nem műszaki vagy üzleti résztvevők között egy szoftverkészítő projektben. Arra ösztönzi a csapatokat, hogy beszélgetéssel és konkrét példákkal hivatalossá tegyék az alkalmazás működésének közös megértését. A tesztvezérelt fejlesztésből (TDD) alakult ki. A viselkedésvezérelt fejlesztés ötvözi a TDD általános technikáit és elveit a tartományvezérelt tervezés és objektumorientált elemzés és tervezés ötleteivel, hogy a szoftverfejlesztő és -kezelő csapatok számára megosztott eszközöket és közös folyamatot biztosítson a szoftverfejlesztésben való együttműködéshez.

Bár a BDD elsősorban egy ötlet arról, hogy hogyan kell kezelni a szoftverfejlesztésben mind az üzleti érdekeket, mind a műszaki betekintést, a gyakorlatban a BDD nem vállalja, hogy a speciális szoftvereszközök támogassák a fejlesztési folyamatot. Bár ezeket az eszközöket gyakran kifejezetten a BDD-projektekben való használatra fejlesztették ki, a tesztalapú fejlesztést támogató eszközök speciális formáinak tekinthetők. Az eszközök arra szolgálnak, hogy mindenütt hozzáautomatizálják az aktuális nyelvet, amely központi témája a BDD.

A BDD-t nagyrészt megkönnyíti egy egyszerű tartományspecifikus nyelv (DSL) használata természetes nyelvű konstrukciók (pl. angolszerű mondatok) használatával, amelyek kifejezhetik a viselkedést és a várt eredményeket. Tesztszkriptek már régóta népszerű alkalmazása DSLs különböző fokú kifinomultsága. A BDD tekinthető hatékony technikai gyakorlatnak, különösen, ha a "problématér" az üzleti probléma megoldására összetett.

Előzmények[szerkesztés]

A viselkedésvezérelt fejlesztés a tesztalapú fejlesztés kiterjesztése: fejlesztés, amely egy egyszerű, tartományspecifikus parancsfájlnyelvet használ. Ezek a DSL-ek strukturált természetes nyelvi állításokat konvertálnak végrehajtható tesztekké. Az eredmény egy adott funkció elfogadási feltételeivel és a funkció érvényesítéséhez használt tesztekkel való szorosabb kapcsolat. Mint ilyen, ez általában egy természetes kiterjesztésű TDD-vizsgálat.

A BDD a következőkre összpontosít:

  • Hol kezdjem a folyamatot
  • Mit kell tesztelni, és mit nem tesztelni
  • Mennyit kell tesztelni egy helyen
  • Mit kell vizsgálni
  • Hogyan értsük meg, miért nem sikerül egy teszt

Középpontjában áll, hogy egy egység tesztelésének és elfogadásának vizsgálatának elkerülése érdekében kérdések merülnek fel. A BDD például azt javasolja, hogy az egységtesztnevek egész mondatok legyenek, amelyek feltételes igével kezdődnek (például angolul kell írni), és az üzleti érték sorrendjében kell írni. Az elfogadási teszteket a felhasználói történet szabványos, agilis keretrendszerének használatával kell megírni: "[szerepként] [funkciót] szeretnék, hogy [előny] legyen". Az elfogadási kritériumokat forgatókönyvekben kell megírni, és osztályokként kell végrehajtani: Tekintettel [kezdeti kontextusra], amikor [esemény bekövetkezik], majd [bizonyos eredmények biztosítása].

Ettől a ponttól kezdve sokan fejlesztettek ki BDD-keretrendszereket az évek során, végül egy kommunikációs és együttműködési keretrendszerként alakítva ki a fejlesztők, a minőségbiztosítási rendszer és a nem műszaki vagy üzleti résztvevők számára egy szoftverprojektben. A 2009 novemberében Londonban az "Agile specifications, BDD and Testing eXchange" során Dan Northa következő leírást adta a BDD-ről:

A BDD egy második generációs, külső, pull-alapú, több érdekelt fél, többszintű, nagy automatizálású, agilis módszertan. Leírja a jól meghatározott kimenetekkel való interakciók ciklusát, ami a működő, tesztelt szoftverek szállítását eredményezi.

Egy interjú során Dan North a GOTO konferencián 2013-ban, Liz Keogh a következőt állította a BDD-ről:

Példákat használ, hogy átbeszéljék, hogyan viselkedik egy alkalmazás... És beszélgetünk ezekről a példákról.

Dan North létrehozott egy BDD keretrendszert, a JBehave-t, amit egy story-szintű BDD keretrendszer követett Ruby számára, RBehave néven, amelyet később integráltak az RSpec projektbe. Együtt dolgozott David Chelimskyvel, Aslak Hellesøyvel és másokkal az RSpec fejlesztésén, valamint a "The RSpec Book: Behaviour Driven Development with RSpec, Cucumber, and Friends" című könyv megírásában is. Az első történetalapú keret RSpec később helyébe Cucumber, elsősorban Aslak Hellesøy által fejlesztett. Capybara, amely része a Cucumber vizsgálati keret egy ilyen webalapú teszt automatizálási szoftver.

A BDD alapelvei[szerkesztés]

A tesztvezérelt fejlesztés olyan szoftverfejlesztési módszertan, amely lényegében kimondja, hogy a szoftverfejlesztőnek minden egyes szoftveregység esetében:

  • először határozza meg az egységteszteket
  • csináljanak sikertelen teszteket
  • ezután végrehajtja az egységteszteket;
  • végül ellenőrizze, hogy az egységtesztek végrehajtása sikeressé teszi-e a teszteket.

Ez a meghatározás nem pontos, mert lehetőséget ad a magas szintű szoftverkövetelményekre, az alacsony szintű technikai részletekre, valamint további elemekre vonatkozó tesztek elvégzésére. Egy jó megközelítése a BDD-nek ezek után az, hogy a TDD olyan továbbfejlesztett változata, ami szigorúbb döntéseket hoz, mint maga a TDD.

A viselkedés vezérelt fejlesztés meghatározza, hogy a szoftver bármely egységének tesztjeit az egység kívánt viselkedése szerint kell meghatározni. Az agilis szoftverfejlesztésből a "kívánt viselkedés" ebben az esetben a vállalkozás által meghatározott követelményekből áll, azaz a kívánt viselkedésből, amely üzleti értéket képvisel bármilyen szervezet számára, amely az építés alatt álló szoftveregységet bízta meg. A BDD gyakorlatán belül ezt "külső tevékenységnek" nevezik.

Viselkedési előírások[szerkesztés]

Ezt követően az alapvető választás, a második választás által a BDD-hez kapcsolódik, hogy a kívánt viselkedést meg kell határozni. Ezen a területen BDD úgy dönt, hogy egy félformális formátum viselkedési specifikáció, amely kölcsönzött felhasználói történet előírások területén objektumorientált elemzés és design. Ennek a formátumnak a forgatókönyve a Hoare-logika alkalmazásaként tekinthető, a helyzet domain nyelvét használó szoftveregységek viselkedési specifikációjára.

A BDD azt határozza meg, hogy az üzleti elemzőknek és fejlesztőknek együtt kell működniük ezen a területen, és meg kell határozniuk a felhasználói történetek viselkedését, amelyek mindegyike kifejezetten le van írva egy dedikált dokumentumba. Minden felhasználói történetnek valamilyen módon a következő struktúrát kell követnie:

Cím
Egy explicit cím.
Narratíva
Rövid bevezető rész a következő szerkezettel:
  • As a (mint): az a személy vagy szerep, aki vagy amely a funkció előnyeit élvezheti;
  • I want (azt akarom): a funkció;
  • so that (úgy, hogy): a funkció előnye vagy értéke.
Elfogadási kritériumok
A narratíva minden egyes forgatókönyvének leírása a következő szerkezettel:
  • Given - Adott: a forgatókönyv elején, egy vagy több záradékban szereplő kezdeti környezet;
  • When - Mikor: a forgatókönyvet kiváltó esemény;
  • Then - Ezután: a várt eredmény, egy vagy több záradékban.

A BDD-ben nincsenek hivatalos követelmények, hogy pontosan hogyan kell ezeket a felhasználói történeteket leírni, de ez nem jelenti azt, hogy minden esetben a BDD segítségével el lehet érni egy egyszerű, szabványosított formátumban leírt a felhasználói történetet, amely magában foglalja a fent felsorolt elemeket. Azonban 2007-ben Dan North egy olyan szöveges formátum sablonját javasolta, amely széles körben követi a különböző BDD-szoftvereszközöket. Egy nagyon rövid példa erre a formátumra így nézhet ki:

(Title) Cím: A visszaküldések és a cserék a készletbe kerülnek.

(As a) Üzlettulajdonosként
(I want) Cikkeket szeretnék visszaadni a készlethez, amikor visszaküldik.
(so that) Nyomon tudjam követni a leltárt.

1. forgatókönyv: A visszatérítésre visszaküldött cikkeket hozzá kell adni a készlethez.
(Given) Tekintettel arra, hogy egy ügyfél korábban vásárolt egy fekete pulóvert tőlem
(And) És van három fekete pulóverem a leltárban,
(When) Amikor visszaadják a fekete pulóvert visszatérítésre,
(Then) Akkor négy fekete pulcsit kéne leltárba raknom.

2. forgatókönyv: A kicserélt cikkeket vissza kell adni a készletbe.
(Given) Tekintettel arra, hogy egy ügyfél korábban vásárolt egy kék ruhát tőlem
(And) és van két kék ruha
(And) és három fekete ruhadarab a leltárban,
(When) amikor a kék ruhát fekete ruhadarabra cserélik,
(Then) akkor három kék ruhadarabot kellene leltárba raknom.
(And) és két fekete ruhadarab a leltárban.

A forgatókönyveket ideális esetben deklaratív módon fogalmazzák meg, nem pedig üzleti nyelven, hivatkozással a felhasználói felület azon elemeire, amelyeken keresztül a kölcsönhatások zajlanak.

Ezt a formátumot a gherkin nyelvnek nevezik, amelynek szintaxisa hasonló a fenti példához. A kifejezés Cucumber, JBehave, Lettuce nevéhez köthető és Behat szoftvereszközöknek nevezik.

Specifikáció mint a mindenütt jelenlévő nyelv[szerkesztés]

Viselkedésvezérelt fejlesztés kölcsönzi a koncepció a mindenütt jelenlévő nyelv, domain alapú design. A mindenütt jelenlévő nyelv egy (félig)formális nyelv, amelyet a szoftverfejlesztő csapat minden tagja megoszt – szoftverfejlesztők és nem műszaki személyzet egyaránt. A szóban forgó nyelvet a csapat minden tagja használja és fejleszti, mint a szóban forgó szoftver domainjének megvitatására. Ily módon a BDD a szoftverprojekt különböző szerepei közötti kommunikáció eszköze lesz.

A szoftverfejlesztés gyakori kockázata a fejlesztők és az üzleti érdekelt felek közötti kommunikációs bontás. A BDD a kívánt viselkedés specifikációját használja a projekt csapattagjai számára mindenütt jelenlévő nyelvként. Ez az oka annak, hogy a BDD ragaszkodik a félhivatalos nyelv viselkedési specifikációjához: néhány formalitás követelmény, hogy a mindenütt ugyanazt a nyelvet használják. Ezen túlmenően, miután egy ilyen mindenütt jelenlévő nyelv létrehoz egy domain modell előírást, amellyel a specifikációkat lehet indokolni hivatalosan. Ez a modell képezi a rendelkezésre álló különböző BDD-támogató szoftvereszközök alapját is.

A fenti példa létrehoz egy felhasználói történetet egy fejlesztés alatt lévő szoftverrendszerhez. Ez a felhasználói történet azonosítja az érdekelt feleket, az üzleti hatást és az üzleti értéket. A forgatókönyv ismerteti az előfeltétel, a kiváltó és várható eredményt. E részek mindegyikét pontosan azonosítja a nyelv formálisabb része (például a Given kifejezés kulcsszónak tekinthető), és ezért valamilyen módon feldolgozható egy olyan eszköz, amely megérti a mindenütt jelenlévő nyelv formális részeit.

A legtöbb BDD-alkalmazás szövegalapú DSL-eket és specifikációs megközelítéseket használ. Az integrációs forgatókönyvek grafikus modellezése azonban a gyakorlatban is sikeresen alkalmazva lett, például tesztelési célokra.

Speciális eszköztámogatás[szerkesztés]

Hasonlóan a tesztalapú tervezési gyakorlathoz, a viselkedésalapú fejlesztés is speciális támogatási eszközök használatát feltételezi a projektben. Annyi, hogy ha BDD van, az sok tekintetben, egy konkrétabb változata a TDD-nek, de több igényt támaszt a fejlesztő, mint az alapvető TDD.

Eszközgyártási alapelvek[szerkesztés]

Elvileg a BDD egy támogatási eszköz, egy tesztelési keretrendszere a szoftvernek, ugyanúgy, mint az eszközök, amelyek támogatják a TDD-t. Azonban, ahol a TDD-eszközök általában meglehetősen szabad formátumúak, amit megengedett a vizsgálatok meghatározása, a BDD eszközök kapcsolódnak a mindenütt jelenlévő nyelvhez.

Mint már említettük, a mindenütt jelenlévő nyelv lehetővé teszi lehetővé az üzleti elemzők számára, hogy olyan módon írják le a viselkedési követelményeket, amelyet a fejlesztők is megértenek. A BDD támogatási eszköz elve, hogy ugyanezeket a követelményeket tartalmazó dokumentumokat tesztgyűjteményként közvetlenül végrehajthatóvá tegye. Ha ez nem érhető el a műszaki eszközhöz kapcsolódó okok miatt, amelyek lehetővé teszik a specifikációk végrehajtását, akkor vagy a viselkedési követelmények írási stílusát kell módosítani, vagy az eszközt kell megváltoztatni. A viselkedési követelmények pontos megvalósítása eszközönként változó, de az agilis gyakorlat a következő általános folyamattal állt elő:

  • Az eszközelem beolvas egy specifikációs dokumentumot.
  • Az eszközkezelés közvetlenül érti a mindenütt jelenlévő nyelv teljesen formális részeit (például a fenti példában megadott kulcsszót). Ennek alapján az eszköz minden forgatókönyvet értelmes záradékokra bont.
  • A forgatókönyv minden egyes záradéka valamilyen paraméterré alakul át a felhasználói történet teszteléséhez. Ez a rész a szoftverfejlesztők projektspecifikus munkáját igényli.
  • A keretrendszer ezután végrehajtja a tesztet az egyes forgatókönyvekhez, az adott forgatókönyv paramétereivel.

Dan North számos olyan keretrendszert fejlesztett ki, amelyek támogatják a BDD-t (beleértve a JBehave-t és az RBehave-t), amelyek működése a felhasználói történetek rögzítéséhez javasolt sablonon alapul. Ezek az eszközök szöveges leírást használnak a használati esetekhez, és számos más eszköz (például a CBehave) követte a példájukat. Azonban ez a formátum nem szükséges, és így vannak más eszközök, amelyek más formátumokat is használnak. Például a Fitnesse (amely a döntési táblázatok köré épül) szintén a BDD bevezetésére szolgál.

Eszközök példái[szerkesztés]

Számos különböző példa van a BDD-szoftvereszközök használatara: a projektek, különböző platformok és programozási nyelvek.

Talán a legismertebb a JBehave, amelyet Dan North, Elizabeth Keogh és még sokan mások fejlesztettek ki. A következő példa a projektből származik:

Fontolja meg a Game of Life végrehajtását. Előfordulhat, hogy egy tartományszakértő (vagy üzleti elemző) meg szeretné adni, hogy mi történjen, ha valaki a játékrács kezdő konfigurációját állítja be. Ehhez érdemes példát mutatnia a sejteket váltó személy által tett számos lépésre. Átugorva a narratív részt, ezt úgy teheti meg, hogy a következő forgatókönyvet írja be egy egyszerű szöveges dokumentumba (amely a JBehave által értelmezett bemeneti dokumentum típusa):

Given a 5 by 5 game
When I toggle the cell at (3, 2)
Then the grid should look like
.....
.....
.....
..X..
.....
When I toggle the cell at (3, 1)
Then the grid should look like
.....
.....
.....
..X..
..X..
When I toggle the cell at (3, 2)
Then the grid should look like
.....
.....
.....
.....
..X..

A félkövér nyomtatás nem része a bemenetnek; itt található annak bemutatása, hogy mely szavakat ismerik el hivatalos nyelvként. JBehave felismeri a megadott kifejezéseket (előfeltételként, amely meghatározza a forgatókönyv kezdetét), When (eseményindítóként) és Then (utófeltételként, amelyet az eseményindítót követő művelet eredményeként kell ellenőrizni). Ennek alapján a JBehave képes elolvasni a forgatókönyvet tartalmazó szövegfájlt, és záradékokba (beállítási záradékba, majd három eseményindítóba, ellenőrizhető feltételekkel) elemezni. A JBehave ezután átveszi ezeket a záradékokat, és továbbítja azokat olyan kódba, amely képes tesztet indítani, reagálni az eseményindítókra és ellenőrizni az eredményt. Ezt a kódot a fejlesztőknek kell megírni. (A JBehave Java-t használ). Ebben az esetben a kód a következőképpen nézhet ki:

private Game game;
private StringRenderer renderer;

@Given("a $width by $height game")
public void theGameIsRunning(int width, int height) {
    game = new Game(width, height);
    renderer = new StringRenderer();
    game.setObserver(renderer);
}
    
@When("I toggle the cell at ($column, $row)")
public void iToggleTheCellAt(int column, int row) {
    game.toggleCellAt(column, row);
}

@Then("the grid should look like $grid")
public void theGridShouldLookLike(String grid) {
    assertThat(renderer.asString(), equalTo(grid));
}

A kód egy módszerrel rendelkezik a forgatókönyv minden típusú záradékához. JBehave azonosítja, hogy melyik módszer az, amely záradék használata révén azonosítja a jegyzeteket, és hívja meg az egyes módszereket sorrendben, miközben a forgatókönyvet futtatja. A forgatókönyv minden egyes záradékában szereplő szövegnek meg kell egyeznie az adott záradék kódjában megadott sablonszöveggel (például egy adott forgatókönyvben várhatóan az "X by Y játék" űrlap záradéka követi). A JBehave támogatja a záradékok sablonokkal való egyeztetését, és beépített támogatást nyújt a sablonokból való kitárolási kifejezések kiválasztásához és a tesztkódban lévő metódusok paraméterként való átadásához. A tesztkód minden egyes záradéktípushoz biztosít implementációt egy olyan forgatókönyvben, amely kölcsönhatásba lép a tesztelt kóddal, és a forgatókönyv alapján végez tesztet. Ebben az esetben:

  • The theGameIsRunning method reacts to a Given clause by setting up the initial game grid.
  • The iToggleTheCellAt method reacts to a When clause by firing off the toggle event described in the clause.
  • The theGridShouldLookLike method reacts to a Then clause by comparing the state of the game grid to the expected state from the scenario.

Ennek a kódnak az elsődleges funkciója, hogy hidat kell építenie egy szövegfájl és a tesztelt kód között. Vegye figyelembe, hogy a tesztkód hozzáfér a tesztelt kódhoz (ebben az esetben egy példány), és nagyon egyszerű jellegű. A tesztkódnak egyszerűnek kell lennie, különben a fejlesztőnek teszteket kell írnia a tesztjeihez.

Végül a tesztek futtatásához a JBehave-nek szüksége van néhány vízvezeték-kódra, amely azonosítja azokat a szövegfájlokat, amelyek forgatókönyveket tartalmaznak, és amelyek függőségeket (például a sorozatpéldányait) bejuttatják a tesztkódba. Ez a vízvezeték-szerelési kód itt nem látható, mivel ez a JBehave műszaki követelménye, és nem kapcsolódik közvetlenül a BDD-stílusú tesztelés elvéhez.

Történet kontra specifikáció[szerkesztés]

A viselkedés-vezérelt fejlesztés külön alkategóriáját olyan eszközök alkotják, amelyek a specifikációkat a felhasználói történetek helyett, beviteli nyelvként használják. Egy példa erre a stílus az RSpec eszköz, amelyet eredetileg Dan North fejlesztett ki. A specifikációs eszközök nem a felhasználói szövegegységeket használják beviteli formátumként a teszt forgatókönyvekhez, hanem inkább funkcionális specifikációkat használnak a tesztelt egységekhez. Ezek a specifikációk gyakran technikai jellegűek, mint a felhasználói történetek, és általában kevésbé kényelmesek az üzleti személyzettel való kommunikációhoz, mint a felhasználói történetek. Egy ilyen specifikáció például így nézhet ki:

Specification: Stack

When a new stack is created
Then it is empty

When an element is added to the stack
Then that element is at the top of the stack

When a stack has N elements 
And element E is on top of the stack
Then a pop operation returns E
And the new size of the stack is N-1

Egy ilyen specifikáció pontosan meghatározhatja a tesztelt összetevő viselkedését, de kevésbé jelentőségteljes az üzleti felhasználók számára. Ennek eredményeképpen a specifikáción alapuló tesztelés a BDD gyakorlatban a történetalapú tesztelés kiegészítéseként látható, és alacsonyabb szinten működik. A specifikációs tesztelést gyakran a szabad formátumú egységtesztelés helyettesítésének tekintik.

Specifikáció vizsgálati eszközök, mint a RSpec és JDave némileg eltérnek a JBehave-től. Ezeket alternatíváknak tekintik. Egy rspec-teszt például a következőképpen nézhet ki:


describe Hash do
  let(:hash) { Hash[:hello, 'world'] }

  it { expect(Hash.new).to eq({}) }

  it "hashes the correct information in a key" do
    expect(hash[:hello]).to eq('world')
  end

  it 'includes key' do
    hash.keys.include?(:hello).should be true
  end
end

Ez a példa a végrehajtható kódba ágyazott olvasható nyelvű specifikációt mutatja be. Ebben az esetben az eszköz választása az, hogy a specifikáció nyelvét formalizálja a tesztkód nyelvére, a nevű és a módon elnevezett módszerek hozzáadásával. Szintén ott van a specifikáció előfeltétele – a szakasz meghatározza azokat az előfeltételeket, amelyeken a specifikáció alapul.

A vizsgálat eredménye a következő lesz:

 Hash
   should eq {}
   includes key
   hashes the correct information in a key

The Three Amigos[szerkesztés]

A The Three Amigos, más néven a "Specifikáció Workshop", egy találkozó, ahol a termék tulajdonosai tárgyalják a követelmény specifikációt a különböző érdekelt felek, mint a QA és a fejlesztő csapat között. A vita fő célja a beszélgetés kiváltása és a hiányzó specifikációk azonosítása. A vita is ad egy lehetőséget a QA, a fejlesztőcsapat és a termék tulajdonos között, hogy egymás szemszögéből is gazdagítani tudják a követelményt, és meggyőződjenek arról, hogy a megfelelő termék készül el.

A The Three Amigos:

  • Üzleti - Az üzleti felhasználó szerepe, hogy csak a problémát határozza meg (és ne merészkedjen semmilyen megoldásra)
  • Fejlesztés - A fejlesztők feladata megoldani az adott problémát
  • Tesztelés - A tesztelők szerepe a megoldás megkérdőjelezése, a "Mi lenne, ha" forgatókönyveken keresztül való különböző lehetőségek felvetése és a megoldás pontosabbá tételének elősegítése a probléma megoldásához.