Vergleich: BDD und TDD
Juni 17, 2009 at 9:04 nachmittags 6 Kommentare
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.
6 Kommentare Füge Deinen hinzu
Kommentar verfassen
Diesen Artikel zurückverfolgen | Abonniere Kommentare via RSS Feed
1.
Bernd Schiffer | Juni 17, 2009 um 9:44 nachmittags
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 | Juni 18, 2009 um 7:00 vormittags
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 | Juni 18, 2009 um 8:00 vormittags
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 | Juni 24, 2009 um 12:35 nachmittags
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 | Juni 30, 2009 um 4:41 nachmittags
[...] 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 | Juli 8, 2009 um 7:09 nachmittags
[...] Während meiner Ruby-Übungen habe ich auch das BDD-Framework RSpec verwendet. Auch sehr schön. Von den Erfahrungen habe ich bereits berichtet. [...]