2010-10-17

Simpel Behavior Driven Development

Her er et eksempel på en meget simpel metode til at at lave BDD style tests med MS Test frameworket.

Der findes utallige komponenter til at at lave mere flydende og måske også mere læsbare test cases til BDD, men jeg lide denne mere simple metode, som ikke kræver andet end diciplin fra dem der skriver test koden og så selvfølgelig gode user stories at tage udgangspunkt i.

Jeg har her til lejligheden opfundet en ny regnemaskine, der har en række krav, som afviger lidt fra en normal lommeregner.

Feature: Addition

 User story: 
  As an accountant I would like to add two numbers.

 Acceptance Criteria:
  Given a positive number
  When added to a positive number
  Then the result should be the sum of the numbers

  Given a zero
  When added to a positive number
  Then the result should be zero

  Given a negative number
  When added to a positive number
  Then the result should be zero

Som man kan se er dette ikke helt almindelige krav til en regnemaskine, men det er heller ikke det der er det vigtige i denne omgang.

Disse krav kunne sagtens testes via "gammeldags" TDD og få det ønskede resultat. Men det som jeg ser som målet med BDD er at kunne vise kunden (Product Owner) at de krav som der er stillet er opfyldt, længe før at et evt brugerinterface er lavet færdigt, og dette egner de fleste testresultater fra TDD sig ikke til. Selvom man laver gode navne på sine tests og variable, så er det jo ikke ensbetydende med at de er forståelige for kunden.

Derfor kan man istedet udnytte det fulde potentiale af udviklingsmiljøet og bruge namespaces, klasse- og metodenavne til at beskrive hvilken user story med tilhørende krav der bliver testet.


Her er et eksempel på dette
namespace Feature_Addition._As_an_Accountant._I_would_like_to
{
    [TestClass]
    public class _add_two_numbers
    {

        Calculator sut;
        [TestInitializeAttribute]
        public void SetUp()
        {
            sut = new Calculator();
        }

        [TestMethod]
        public void Given_a_positive_number_When_added_to_a_positive_numbers_Then_result_should_be_the_sum()
        {
            Assert.AreEqual(3, sut.Add(1, 2));
        }

        [TestMethod]
        public void Given_a_zero_When_added_to_a_positive_number_Then_result_should_be_0()
        {
            Assert.AreEqual(0, sut.Add(0, 2));
        }

        [TestMethod]
        public void Given_a_negative_number_When_added_to_a_positive_number_Then_result_should_be_0()
        {
            Assert.AreEqual(0, sut.Add(-1, 2));
        }
    }
}

Som man kan se er hele user storyen med alle 3 acceptance criteria repræsenteret i denne test klasse. Og når man kører disse test, så får man følgende resultat i Test Results vinduet


Jeg har tilføjet kolonnen "Full Class Name" til listen, for bedre at kunne se hele user storien i test resultatet. Alternativt skal man angive hele navnet i hver test metode, men det vil kun gøre navnene besværlige at læse og  kræve at den samme sætning bliver gentaget igen og igen.

Dette test resultat kunne man selvfølgelig sagtens levere, som dokumentation for at kundens krav er opfyldt, men det er nok ikke så læsbart som man kunne ønske. Istedet kan man udnytte at MSTest laver en XML fil med resultaterne fra hver testkørsel. Denne XML fil kan man konvertere til HTML format ved hjælp af værktøjet trx2html så man istedet for får dette resultat


Her er et resultat der kan bruges til at dokumentere om kundens krav er opfyldt løbende under udviklingsfasen. Det eneste der mangler er at få denne html rapport automatisk genereret når build serveren har kørt unit tests efter en build.

2 kommentarer:

  1. Ganske udmærket til enkelte kriterier. Udfordringen opstår når dit kriterium er mere komplekst, fx:

    Given A
    And B
    And C
    When X
    And Y
    And Z
    Then P
    And Q
    And R

    Personligt anvender jeg StoryQ som BDD framework: http://storyq.codeplex.com/

    /Bakkegaard

    SvarSlet
  2. Jeg kan godt se hvad du mener, jeg har dog heldigvis ikke endnu set så kompliceret en kravsbeskrivelse :-).

    Jeg har kigget på StoryQ før og vil give dig ret i at det er meget bedre til at beskrive sådanne cases, men man kunne måske se denne metode som en indgangsvinkel til at starte med BDD og så udvikle det til at anvende StoryQ eller et af de andre BDD frameworks der findes.

    SvarSlet