it-swarm.com.de

Was ist der Unterschied zwischen dem Schreiben von Testfällen für BDD und TDD?

Ich habe gelernt, Testfälle für BDD (Behavior Driven Development) mit specflow zu schreiben. Wenn ich umfassende Tests mit BDD schreibe, muss der TDD-Test (Test Driven Development) separat geschrieben werden? Ist es notwendig, Testfälle für TDD und BDD separat zu schreiben, oder sind sie effektiv dasselbe?

Es scheint mir, dass beide gleich sind, der einzige Unterschied besteht darin, dass BDD-Testfälle von Nicht-Entwicklern und Testern verstanden werden können.

247
arjun

Der Unterschied zwischen BDD und TDD besteht darin, dass BDD mit einem B beginnt und TDD mit einem T beginnt. Im Ernst, das Problem bei TDD ist, dass sich zu viele Entwickler beim Schreiben ihrer Komponententests auf das "Wie" konzentrierten, sodass sie sehr erfolgreich waren Sprödigkeitstests, die nur bestätigten, dass das System das tut, was es tut.

BDD bietet ein neues Vokabular und konzentriert sich somit auf das Schreiben eines Unit-Tests. Grundsätzlich handelt es sich um einen funktionsgesteuerten Ansatz für TDD.

214
Michael Brown

Behavior Driven Development ist eine Erweiterung/Überarbeitung von Test Driven Development. Ihr Zweck ist es, den Entwicklern des Systems (d. H. Den Entwicklern) dabei zu helfen, geeignete Tests zum Schreiben zu identifizieren - dh Tests, die das von den Stakeholdern gewünschte Verhalten widerspiegeln. Der Effekt ist am Ende derselbe - entwickeln Sie den Test und dann den Code/das System, das den Test besteht. Die Hoffnung bei BDD ist, dass die Tests tatsächlich nützlich sind, um zu zeigen, dass das System die Anforderungen erfüllt.

UPDATE

Codeeinheiten (einzelne Methoden) sind möglicherweise zu detailliert, um das durch die Verhaltenstests dargestellte Verhalten darzustellen. Sie sollten sie jedoch weiterhin mit Komponententests testen, um sicherzustellen, dass sie ordnungsgemäß funktionieren. Wenn Sie dies mit "TDD" -Tests meinen, dann brauchen Sie sie immer noch.

51
Matthew Flynn

BDD verwendet eine sogenannte "Ubiquitous Language", eine Wissensbasis, die sowohl vom Entwickler als auch vom Kunden verstanden werden kann. Diese allgegenwärtige Sprache wird verwendet, um die erforderlichen Anforderungen und Tests auf der Ebene des Kundenverständnisses zu gestalten und zu entwickeln.

Im Rahmen der von BDD vorgegebenen Anforderungen und Tests verwenden Sie "normales" TDD, um die Software zu entwickeln. Die so erstellten Komponententests dienen als Testsuite für Ihren Implementierungscode, während die BDD-Tests mehr oder weniger als Abnahmetests für den Kunden dienen.

26
Robert Harvey

Nach meiner Erfahrung ist das größte Problem mit TDD das " T ". Dies führt dazu, dass Laien (Manager, Tester, Nicht-TDD-Entwickler) dies in ihren Gedanken mit der traditionellen "Test" -Phase eines Wasserfallstils nach der Entwicklung gleichsetzen. Das ist etwas, das jeder in den Griff bekommen kann.

Das Problem, mit dem viele zu kämpfen haben, ist, dass TDD für Entwickler und nicht für Tester gedacht ist. Richtig gemacht TDD ist nicht in erster Linie eine Teststrategie oder ein Abnahmetest-Tool, sondern eine Technik, die ein gutes Software-Design von Grund auf fördert - kleine, lose gekoppelte Klassen, klare, gut definierte Schnittstellen und kontinuierlich bereinigter Code durch fortlaufendes Refactoring. Refactoring, das routinemäßig, häufig und aus einer Vertrauensstellung heraus durchgeführt wird.

Dass Sie zufällig eine umfassende Testsuite erhalten, die einen Teil Ihres CI/Build-Prozesses bilden kann, ist ein Bonus, nicht das Ziel.

BDD ergänzt dies, indem es die Lücke zwischen Geschäftsanforderungen und Akzeptanztests auf höherer Ebene schließt. Es ist die Befriedigung der BDD-Suite, die den Entwicklungsprozess abdeckt und feststellt, wann das Produkt insgesamt angemessen geliefert wurde.

20
sim303

Die Unterschiede zwischen TDD und BDD sind subtil und beschränken sich hauptsächlich auf die Sprache . BDD-Tests werden häufig in folgender Form geschrieben:

public void shouldBuyBread() throws Exception {
   //given  
   given(seller.askForBread()).willReturn(new Bread());

   //when
   Goods goods = shop.buyBread();

   //then
   assertThat(goods, containBread());
 }  

Wenn Sie den Test in Bezug auf Verhalten einrahmen, hilft dies dabei, die Verantwortung der Klasse zu erfassen, und führt zu einem besseren Design (zumindest laut BDD'ern). BDD konzentriert sich manchmal auf ausführbare Spezifikationen , die Ihre Domain-Experten/Kunden verstehen können.

BDD ist auch eher mit dem verbunden, was Martin Fowler nennt "Outside-In" - oder "Mockist" -Tests , im Gegensatz zur staatlichen Verifizierung.

19
Garrett Hall

Da meine letzte Antwort nicht sehr erfolgreich war, werde ich einen sehr einfachen Ansatz versuchen.

  • Behaviour Driven Development ist eine Teilmenge von Test Driven Development
  • TDD konzentriert sich auf jeden einzelnen Unit-Test für jede Funktion, egal was er tut. BDD konzentriert sich auf Software, die zählt
  • Idiom. TDD begnügt sich mit Tests, BDD erzwingt das Format Geschichtenerzählen

JavaScript-Beispiele

Unit-Tests in Jasmin (BDD)

describe("A suite", function() {
  it("contains spec with an expectation", function() {
    expect(true).toBe(true);
  });
});

Unit-Tests in jsUnity (TDD)

function test_lists() { assert.areEqual([1, 2, 3], [1, 2, 3]) }

Hier sind einige Python-Bibliotheken , mit denen Sie mehr BDD -ähnliche Tests mit unittest Frameworks erstellen können:

  • Salat : Gurke für Python
  • HamCrest
12
percebus

BDD fügt den Tests eine weitere Abstraktionsebene hinzu. Der Code auf höherer Ebene (normalerweise in txt) beschreibt, was das System testet, der Code auf niedrigerer Ebene beschreibt, wie es es testet. Ein BDD-Framework kann also ein TDD-Framework im Code der unteren Ebene verwenden.

Dies hilft sehr, indem es trocken bleibt. Mit TDD können Sie leicht "nasse" Tests erhalten, die viel Code-Duplizierung enthalten, wodurch sie leicht zu brechen sind, indem der Code und die damit verbundenen Tests überarbeitet werden. Mit BDD müssen Sie nur die untere Abstraktionsebene ändern, indem Sie den Code umgestalten. Wenn sich die Spezifikation nicht ändert, ändert sich der Code der höheren Ebene nicht.

Übrigens. Dies ist einfacher, sauberer Code. Normalerweise reicht es aus, die Inhalte auf hoher Abstraktionsebene zu lesen, um zu verstehen, was sie tun, und nur dann tiefer in den Testcode auf niedrigerer Abstraktionsebene einzusteigen, wenn Sie ihn wirklich benötigen. Dies erleichtert das Verständnis von (Test-) Code im Allgemeinen.

Ein schlechtes Beispiel (weil es zu einfach ist):

Jasmin TDD Stil

calculator.add.specs

describe("Calculator: add", function (){

    it("should be able to add 2 numbers together", function (){
        var total = add(1, 2);
        expect(total).toBe(3);
    });

    it("should be able to add 3 numbers together", function (){
        var total = add(1, 2, 3);
        expect(total).toBe(6);
    });
});

Jasmin-Gurken-BDD-Stil

calculator.specs

feature('Calculator: add')
    .scenario('should be able to add 2 numbers together')
        .when('I enter "1"')
        .and('I add "2"')
        .then('I should get "3"')
    .scenario('should be able to add 3 numbers together')
        .when('I enter "1"')
        .and('I add "2"')
        .and('I add "3"')
        .then('I should get "6"')

calculator.steps

featureSteps('Calculator:')
    .before(function(){
        this.values = [];
        this.total = null;
    })
    .when('I enter "(.*)"', function(value){
        this.values.Push(Number(value));
    })
    .when('I add "(.*)"', function(value){
        this.values.Push(Number(value));
    })
    .then('I should get "(.*)"', function(expectedTotal){
        this.total = add.apply(null, this.values);
        expect(this.total).toBe(Number(expectedTotal));
    });

Implementierung

calculator.js

function add(){
    var args = Array.prototype.slice.call(arguments);
    var total = 0;
    for (var i in args)
        total += args[i];
    return total;
}

Wenn ich nun die Funktion add() in sum() umbenenne, muss ich den TDD-Code an zwei Stellen ändern, während der BDD-Code nur an einer einzigen Stelle im Schritte Datei. Ofc. Das Hinzufügen einer weiteren Abstraktionsebene erfordert mehr Code ...

4
inf3rno

Um es verwirrend zu halten, stellen Sie fest, dass viele Leute BDD jetzt mit Gurke assoziieren. Sie betrachten alle Tests, die Sie mit einer von Gurken abgeleiteten Syntax schreiben, als BDD-Prüfung und alle Tests, die mit einem Unit-Test-Framework (junit, unittest.py usw.) geschrieben wurden, als TDD.

Es ist falsch. Das Medium definiert die Nachricht in diesem Fall nicht. Auch die Verwendung von Mocks (IMHO) nicht.

Der Hauptunterschied wurde bereits festgestellt: BDD ist eine funktionsgesteuerte Technik, die eine allgegenwärtige Sprache und einen Outside-In-Ansatz verwendet. Wir schreiben Spezifikationen (die später als Tests ausgeführt werden) für eine Geschichte oder einen Teil einer Geschichte. Kleinheit und Konkretheit sind wichtig, und es ist eine "Erklärung am Beispiel" dessen, was von diesem Aspekt der Geschichte benötigt/erwartet wird.

BDD-Spezifikationen werden häufig in einer gherkinähnlichen Sprache geschrieben, wenn die Personen, die die Funktion angeben müssen, nicht alle Code lesen/schreiben (häufiger Fall in größeren Organisationen oder wenn ein echter Kunde Teil des Teams ist). Andernfalls ist Essiggurke nicht erforderlich. Diese sind in der Regel das Ergebnis des berühmten 3-Amigos-Treffens: Business, Test, Entwickler machen das alles zusammen. Bei Verwendung eines BDD-Frameworks (Fit, Gurke usw.) sind die Tests langsamer und erfordern etwas mehr Infrastruktur. Daher halten wir diese relativ spärlich - einige pro Story.

TDD wird beim Erstellen von Code verwendet. Der Zweck besteht darin, eine geordnete Abfolge des Schreibens der Funktion mit vielen Möglichkeiten zum Refactoring und mit der angemessenen Sicherheit zu gewährleisten, dass Sie beim Schreiben des neuen Codes nicht versehentlich etwas beschädigen. Es müssen keine Funktionen des Systems beschrieben werden, sondern nur eine Methode (oder einige mit einem gemeinsamen Effekt). Niemand außer Entwicklern muss die hier geschriebenen Tests lesen, aber sie müssen schnell verrückt laufen und Fehler isolieren. Sie laufen verrückt schnell, weil es viele Tests pro Klassenmitgliedsfunktion geben kann ('Methode').

Wenn Sie BDD auf der äußeren Ebene ausführen, ist es aufgrund des Refactorings und der Möglichkeit, Fehler schneller zu erkennen und zu vermeiden, immer noch nützlich, TDD in der inneren Schleife auszuführen.

Es gibt auch keinen Beweis für die Richtigkeit eines großen Systems. Weder ersetzt Pen- und Perf-Tests. Beides gewährleistet keine Gewindesicherheit. Die Tests sind Entwicklungshilfen und keine Garantie für eine perfekte Fehlersicherheit.

2
tottinge