Vergleich: BDD und TDD

June 17, 2009 at 9:04 pm 6 comments


Als XP-Jünger der ersten Stunde wurde ich bereits früh von TDD (Test Driven Development) infiziert. Irgendwann kam eine neue Bewegung auf: BDD (Behaviour Driven Design). Wie viele andere TDDler habe ich lange nicht verstanden, was der Vorteil von BDD sein soll. Das ist mir inzwischen klar geworfen. Ich möchte versuchen, einige der Vorteile in diesem Artikel anhand eines Beispiels zu vermitteln.
Als Beispiel verwende ich mein Terminplaner-Beispiel in Ruby mit RSpec als BDD-Framework.

Im Terminplaner-Test testen wir beispielsweise das Erzeugen von Terminen:

class TerminkalenderTest < RUNIT::TestCase

    ...
    def test_termin_anlegen
        dauer_in_minuten = 180
        termin = @stefans_kalender.new_termin(@jetzt, dauer_in_minuten, "TDD-Dojo")
        assert @stefans_kalender.hat_termin(termin)
        assert_equal("TDD-Dojo", termin.bezeichnung)
        assert_equal(@jetzt, termin.start_zeit)
        assert_equal(dauer_in_minuten, termin.dauer_in_minuten)
        assert_equal(STEFAN, termin.autor)
    end
    ...
end

Als BDD-Spezifikation sieht das ganze noch sehr ähnlich aus:

describe Terminkalender do
    it "should create new meetings" do
        dauer_in_minuten = 180
        termin = @stefans_kalender.new_termin(@jetzt, dauer_in_minuten, "TDD-Dojo")
        @stefans_kalender.hat_termin(termin).should be_true
        termin.bezeichnung.should == "TDD-Dojo"
        termin.start_zeit.should == @jetzt
        termin.dauer_in_minuten.should == dauer_in_minuten
        termin.autor.should == STEFAN
    end
    ...
end

Strukturell sind Test und BDD-Spezifikation identisch. Die BDD-Spezifikation ist bei den Vergleichen lediglich etwas leichter lesbar.
Der Vergleich termin.bezeichnung.should == "TDD-Dojo" ist der natürlichsprachlichen Formulierung "Die Terminbezeichnung sollte 'TDD-Dojo' sein." ähnlicher als assert_equal("TDD-Dojo", termin.bezeichnung).

Wenn wir Test und BDD-Spezifikation weiter vergleichen, finden wir auch strukturelle Unterschiede. So ist am folgenden Test erstmal nicht so fürchterlich viel auszusetzen:

def test_teilnehmer_einladen_und_autor_ist_auch_teilnehmer
    termin = @stefans_kalender.new_termin(@jetzt, 180, "TDD-Dojo")
    termin.lade_teilnehmer_ein(MARTIN)
    termin.lade_teilnehmer_ein(HENNING)

    assert_equal([HENNING, MARTIN, STEFAN], termin.teilnehmer)
    assert_equal(@stefans_kalender.alle_termine, [termin])
    assert_equal(@hennings_kalender.alle_termine, [termin])
end

Wenn man versucht, diesen Testfall direkt nach BDD zu portieren, stößt man schon bei der Benennung auf ein Problem. Wie soll man das vernünftig mit "it" (=Terminkalender) am Satzanfang formulieren? it "invites participants and author is participant" kann man zwar aufschreiben. Zumindest bei mir stellen sich dann aber die Nackenhaare zu Berge. Viel natürlicher scheint mir eine Aufteilung des Tests in mehrere BDD-Spezifikationen:

describe Termin do
    ...

    it "should have the author as a participant" do
        @termin.teilnehmer.should include STEFAN
    end

    it "should invite participants" do
        @termin.lade_teilnehmer_ein MARTIN
        @termin.lade_teilnehmer_ein HENNING 
        @termin.teilnehmer.should == [HENNING, MARTIN, STEFAN]
    end
    ...
end

BDD führt also auf natürlichem Weg zu Spezifikationen, die jeweils kleiner und besser strukturiert sind als Tests.

Wir haben mit BDD also in Summe besser strukturierte, leichter lesbare Spezfikationen.

Entry filed under: 1. Tags: .

Buchtipp: The Google Way Artikel zur agilen Architektur in Objekt-Spektrum

6 Comments Add your own

  • 1. Bernd Schiffer  |  June 17, 2009 at 9:44 pm

    Ich verstehe, wie Dich der sprachliche Umgang beim BDD-Beispiel hin zu kleineren Spezifikationen treibt. Ich verstehe nicht, wie Du mit TDD zu so einer großen Testmethode gekommen bist. Hättest Du – aus meiner Sicht – die Testmethode refaktorisiert (nach SRP oder auch One Assertion), so hättest Du auch mehrere kleinere und strukturiertere Tests bekommen.
    Sofern ich da richtig schlussfolgere gibt’s ein Unentschieden beim Vergleich BDD und TDD.

  • 2. stefanroock  |  June 18, 2009 at 7:00 am

    Der Test ist tatsächlich mit TDD entstanden, aber vor etlichen Jahren. Heute würde mein TDD-Test anders aussehen – nämlich der BDD-Spec sehr ähnlich. Eine Ursache dafür ist aus meiner Sicht, dass wir heute viele BDD-Techniken auch im xUnit-Umfeld anwenden. Aber dazu wollte ich nochmal einen eigenen Blog-Eintrag schreiben.

    Meine These bleibt aber, dass mind. TDD/BDD-Anfängern mit BDD zu besseren Tests/Specs kommen.

  • 3. Jens Himmelreich  |  June 18, 2009 at 8:00 am

    Es gibt einen schönen Aufsatz von Martin Fowler zum Thema: Mocks aren’t Stubs (http://martinfowler.com/articles/mocksArentStubs.htm). Fowler beschreibt zwei Unterschiede im Testansatz: Zustandsbasiertes versus Verhaltensbasiertes Testen und klassisches versus mockbasiertes Testen. Der mockbasierte Ansatz sei der des BDD. Der Lektüre lohnt sich, weil Fowler viele Unterschiede und Konsequenzen in der Art und Weise des Programmierens aufweist, die über ein neues Vokabular hinausgehen. (Eine Relektüre lohnt sich, weil Fowler den Unterschied von Zustand versus Interaktionsbasiertem Testen aus der ersten Version verworfen, durch die zwei Unterschiede ersetzt und weiter ausgearbeitet hat.)

  • 4. marko  |  June 24, 2009 at 12:35 pm

    Ich verstehe gut, dass Du zu dem zweiten Test gekommen bist. Den hätte ich auch gut so schreiben können und ich finde ihn nicht gleich schlecht. Für mich ist ein klassischer, naheliegender Testfall. Weniger ist es dafür ein “Verhaltensbeschreibungsfall”, weswegen der Übergang zu BDD hier hilft, eine andere Sicht zu bekommen und so zu einem besseren Schneiden des Falles führt.

    Übrigens: Das “und” in dem Testnamen ist auch ein Hinweis, das hier zwei Dinge gleichzeitig getestet werden. Nach dem Schreiben des (naheliegenden) Testfalls hätte Dich der sperrige Name nachdenklich machen können, das hier etwas stinkt und beim nochmaligen Betrachten des Tests hättest Du sicherlich auch gesehen, das der Test keinen klaren Fokus hat. Diesen Abstand zu seinem eigenen Code erlangt man jedoch nicht leicht – Pair Programming to the rescue! :-)

  • 5. BDD mit Test-Technologien « Stefan Roock  |  June 30, 2009 at 4:41 pm

    […] 30, 2009 Vor kurzem habe ich einen kurzen Vergleich zwischen TDD und BDD gewagt und BDD präferiert. Bernd Schiffer meinte, die TDD-Tests seien suboptimal und wenn man sie […]

  • 6. Lernen im zweiten Quartal 2009 « Stefan Roock  |  July 8, 2009 at 7:09 pm

    […] Während meiner Ruby-Übungen habe ich auch das BDD-Framework RSpec verwendet. Auch sehr schön. Von den Erfahrungen habe ich bereits berichtet. […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Trackback this post  |  Subscribe to the comments via RSS Feed



%d bloggers like this: