BDD: De første User stories og Acceptance Criteria

Skrevet - Wednesday, July 23rd, 2008 kl. 12:51 | Kategori - Kodning

I mit EconomyDeluxe projekt er det nu tid til at få styr på hvad der er den vigtigste funktionalitet at få på plads først. Efter nøje gennemgang af de User Stories som jeg har skrevet ned på gule post-it’s, har jeg valgt følgende User Stories skrevet efter formlen “Som en…” “Vil jeg gerne…” “Så jeg opnår…” og med tilhørende Acceptance Criteria efter formlen “Under forudsætning af…” “Når…” “Skal…”:

Oprettelse af FinansKonti i KontoPlan

Som en Bogholder
Vil jeg gerne kunne tilføje en FinansKonto til Kontoplanen
Så jeg opnår mulighed for at lave FinansPosteringer på den og kan følge virksomhedens indtægter og udgifter.

Accepteres når:
Under forudsætning af en gyldig FinansKonto
som ikke eksisterer i KontoPlanen.
Når jeg tilføjer den til KontoPlanen
Skal antallet af FinansKonti stige med 1
og KontoPlanen skal indeholde FinansKontoen.

Under forudsætning af en ugyldig, allerede eksisterende eller FinansKonto med værdien null
Når jeg tilføjer den til KontoPlanen
Skal der kastes en Exception.

Sletning af FinansKonti fra KontoPlan

Som en Bogholder
Vil jeg gerne kunne slette ubrugte FinansKonti fra KontoPlanen
Så jeg opnår en strømlinet KontoPlan og kan fjerne fejloprettede FinansKonti.

Accepteres når:
Under forudsætning af en gyldig FinansKonto
Når jeg fjerner den fra KontoPlanen
Skal antallet af FinansKonti falde med 1
og KontoPlanen skal ikke længere indeholde FinansKontoen.

Under forudsætning af en ugyldig eller FinansKonto med værdien null
Når jeg fjerner den til KontoPlanen
Skal der kastes en Exception.

Som et designvalg, har jeg valgt at FinansKonti skal have et unikt nummer. Min erfaring (og jeg har snakket med brugeren… mig, og han er enig) er at bogholdere ikke rigtig kan holde styr på FinansKonti med samme kontonummer.

De nævnte User Stories er også placeret på en statisk side her (på engelsk som vanligt) - hvor de vil blive opdateret og udviklet efterhånden som projektet udvikler sig. Der er selvfølgelig en lang række funktionalitet, jeg har planer om, men de her har den største forretningsværdi for mig nu (de fleste andre afhænger nemlig af dem her). For at påbegynde min iteration (jeg kører efter en tillempet Agil udviklingsmetode som jeg kalder SuperScrumLightXP NuMedExtraKaffe eller SSL NMEK - udtales ssschmæk) er det nu tid til at bore lidt i mine User Stories. Hvad forventer jeg af systemets adfærd - hvornår skal det beskytte mig imod mine egne tåbeligheder, og hvilke krav skal jeg stille til returdata?

Endelig er det tid til lidt kode-gymnastik - vi skal have lavet nogle tests adfærdsspecifikationer. Jeg har valgt at de ovenstående User Stories skal håndteres af GeneralLedger, så i gang med kodeklaskeriet.

using System;
using NUnit.Framework;

[TestFixture()]
public class GeneralLedgerBehaviour
{

#region [UserStory: Adding LedgerAccounts to GeneralLedger]
[Test()]
public void shouldAddLedgerAccountOnAddWithValidLedgerAccount(){}

[Test()]
[ExpectedException(typeof(ArgumentException))]
public void shouldThrowExceptionOnAddWithInvalidLedgerAccount(){}

[Test()]
[ExpectedException(typeof(ArgumentNullException))]
public void shouldThrowExceptionOnAddWithNullLedgerAccount(){}

[Test()]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void shouldThrowExceptionWhenAddingLedgerAccountWithIdenticalId(){}
#endregion

#region[UserStory: Deleting LedgerAccounts from GeneralLedger]
[Test()]
public void shouldDeleteSuppliedExistingLedgerAccount(){}

[Test()]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void shouldThrowExceptionWhenDeletingNonExistingLedgerAccount(){}

[Test()]
[ExpectedException(typeof(ArgumentNullException))]
public void shouldThrowExceptionWhenDeletingNullLedgerAccount(){}
#endregion

}

Det fantastiske (?) er at jeg endnu ikke har skrevet et gram kode i min løsning, men jeg har allerede beskrevet specifikationen til hvordan jeg forventer at mit domain opfører sig. Jeg ville i princippet kunne udlevere denne stump kode og en kop kaffe, og så ville en hvilken som helst kodekarl kunne implementere det. Okay - måske ville det hjælpe lidt, hvis jeg skriver inde i min kode, hvad jeg forventer, men på det tidspunkt, er vi så småt begyndt at snakke om vores løsning - og det reserverer jeg til mit næste indlæg.

Feed | Trackback |

Post a Comment