Leitfaden für JSpec

Leitfaden für JSpec

1. Überblick

Testläufer-Frameworks wieJUnit undTestNG bieten einige grundlegende Assertionsmethoden (assertTrue,assertNotNull usw.).

Dann gibt es Assertion-Frameworks wieHamcrest,AssertJ undTruth, die fließende und reichhaltige Assertion-Methoden mit Namen bereitstellen, die normalerweise mit“assertThat” beginnen.

JSpec is another framework that allows us to write fluent assertions closer to the way we write specifications in our natural language, wenn auch etwas anders als in anderen Frameworks.

In diesem Artikel erfahren Sie, wie Sie JSpec verwenden. Wir zeigen die Methoden, die zum Schreiben unserer Spezifikationen erforderlich sind, und die Meldungen, die im Falle eines Testfehlers gedruckt werden.

2. Maven-Abhängigkeiten

Importieren wir die Abhängigkeit vonjavalite-common, die JSpec enthält:


    org.javalite
    javalite-common
    1.4.13

Für die neueste Version überprüfen Sie bitte dieMaven Central repository.

3. Vergleichsstile vergleichen

Anstelle der typischen Art, auf der Grundlage von Regeln zu behaupten, schreiben wir nur die Spezifikation des Verhaltens. Schauen wir uns ein kurzes Beispiel für die Durchsetzung der Gleichheit in JUnit, AssertJ und JSpec an.

In JUnit schreiben wir:

assertEquals(1 + 1, 2);

Und in AssertJ würden wir schreiben:

assertThat(1 + 1).isEqualTo(2);

So schreiben wir denselben Test in JSpec:

$(1 + 1).shouldEqual(2);

JSpec verwendet denselben Stil wie fließende Assertion-Frameworks, lässt jedoch das führende Schlüsselwortassert /assertThatweg und verwendet stattdessenshould.

Das Schreiben von Behauptungen auf diese Weise macht es zueasier to represent the real specifications und fördert TDD- und BDD-Konzepte.

Schauen Sie, wie dieses Beispiel unserem natürlichen Schreiben von Spezifikationen sehr nahe kommt:

String message = "Welcome to JSpec demo";
the(message).shouldNotBe("empty");
the(message).shouldContain("JSpec");

4. Struktur der Spezifikationen

The specification statement consists of two parts:ist ein Erwartungsersteller und eine Erwartungsmethode.

4.1. Expectation Creator

Der Erwartungserstellergenerates an Expectation object verwendet eine dieser statisch importierten Methoden:a(),the(),it(),$():

$(1 + 2).shouldEqual(3);
a(1 + 2).shouldEqual(3);
the(1 + 2).shouldEqual(3);
it(1 + 2).shouldEqual(3);

Alle diese Methoden sind im Wesentlichen die gleichen - sie existieren nur, um verschiedene Möglichkeiten zur Darstellung unserer Spezifikation bereitzustellen.

Der einzige Unterschied besteht darin, dassthe it() method is type-safe nur einen Vergleich von Objekten des gleichen Typs ermöglicht:

it(1 + 2).shouldEqual("3");

Der Vergleich von Objekten unterschiedlichen Typs mitit() würde zu einem Kompilierungsfehler führen.

4.2. Erwartungsmethode

Der zweite Teil der Spezifikationsanweisung ist die Erwartungsmethode, bei dertells about the required specification wieshouldEqual,shouldContain ist.

Wenn der Test fehlschlägt, zeigt eine Ausnahme vom Typjavalite.test.jspec.TestException eine aussagekräftige Meldung an. Beispiele für diese Fehlermeldungen finden Sie in den folgenden Abschnitten.

5. Eingebaute Erwartungen

JSpec bietet verschiedene Arten von Erwartungsmethoden. Schauen wir uns diese an, einschließlich eines Szenarios für jedes Szenario, in dem die Fehlermeldung angezeigt wird, die JSpec bei einem Testfehler generiert.

5.1. Gleichstellungserwartung

shouldEqual (), shouldBeEqual (), shouldNotBeEqual ()

Diese geben an, dass zwei Objekte gleich sein sollen / nicht, wobei die Methodejava.lang.Object.equals()verwendet wird, um die Gleichheit zu überprüfen:

$(1 + 2).shouldEqual(3);

Fehlerszenario:

$(1 + 2).shouldEqual(4);

würde die folgende Nachricht erzeugen:

Test object:java.lang.Integer == (3)
and expected java.lang.Integer == (4)
are not equal, but they should be.

5.2. Boolesche Eigenschaftserwartung

shouldHave (), shouldNotHave ()

Wir verwenden diese Methoden, umwhether a named boolean property of the object should/shouldn’t return true: anzugeben

Cage cage = new Cage();
cage.put(tomCat, boltDog);
the(cage).shouldHave("animals");

Dies erfordert, dass die KlasseCageeine Methode mit der Signatur enthält:

boolean hasAnimals() {...}

Fehlerszenario:

the(cage).shouldNotHave("animals");

würde die folgende Nachricht erzeugen:

Method: hasAnimals should return false, but returned true

shouldBe (), shouldNotBe ()

Wir verwenden diese, um anzugeben, dass das getestete Objekt etwas sein soll / sollte:

the(cage).shouldNotBe("empty");

Dies erfordert, dass die KlasseCage eine Methode mit der Signatur“boolean isEmpty()”. enthält

Fehlerszenario:

the(cage).shouldBe("empty");

würde die folgende Nachricht erzeugen:

Method: isEmpty should return true, but returned false

5.3. Typ Erwartung

shouldBeType (), shouldBeA ()

Mit diesen Methoden können wir festlegen, dass ein Objekt von einem bestimmten Typ sein soll:

cage.put(boltDog);
Animal releasedAnimal = cage.release(boltDog);
the(releasedAnimal).shouldBeA(Dog.class);

Fehlerszenario:

the(releasedAnimal).shouldBeA(Cat.class);

würde die folgende Nachricht erzeugen:

class com.example.jspec.Dog is not class com.example.jspec.Cat

5.4. Nullability Expectation

shouldBeNull (), shouldNotBeNull ()

Wir verwenden diese, um anzugeben, dass das getestete Objektnull sein soll / sollte:

cage.put(boltDog);
Animal releasedAnimal = cage.release(dogY);
the(releasedAnimal).shouldBeNull();

Fehlerszenario:

the(releasedAnimal).shouldNotBeNull();

würde die folgende Nachricht erzeugen:

Object is null, while it is not expected

5.5. Referenz Erwartung

shouldBeTheSameAs (), shouldNotBeTheSameAs ()

Diese Methoden werden verwendet, um anzugeben, dass die Referenz eines Objekts mit der erwarteten identisch sein soll:

Dog firstDog = new Dog("Rex");
Dog secondDog = new Dog("Rex");
$(firstDog).shouldEqual(secondDog);
$(firstDog).shouldNotBeTheSameAs(secondDog);

Fehlerszenario:

$(firstDog).shouldBeTheSameAs(secondDog);

würde die folgende Nachricht erzeugen:

references are not the same, but they should be

5.6. Erwartung an Sammlung und String-Inhalt

shouldContain(), shouldNotContain() Wir verwenden diese, um anzugeben, dass die getestetenCollection oderMap ein bestimmtes Element enthalten sollen / sollten:

cage.put(tomCat, felixCat);
the(cage.getAnimals()).shouldContain(tomCat);
the(cage.getAnimals()).shouldNotContain(boltDog);

Fehlerszenario:

the(animals).shouldContain(boltDog);

würde die folgende Nachricht erzeugen:

tested value does not contain expected value: Dog [name=Bolt]

Wir können diese Methoden auch verwenden, um anzugeben, dass einString einen bestimmten Teilstring enthalten soll / sollte:

$("Welcome to JSpec demo").shouldContain("JSpec");

Und obwohl es seltsam erscheinen mag, können wir dieses Verhalten auf andere Objekttypen ausweiten, die mit ihrentoString()-Methoden verglichen werden:

cage.put(tomCat, felixCat);
the(cage).shouldContain(tomCat);
the(cage).shouldNotContain(boltDog);

Zur Verdeutlichung würde dietoString()-Methode desCat-ObjektstomCat Folgendes erzeugen:

Cat [name=Tom]

Dies ist eine Teilzeichenfolge dertoString()-Ausgabe descage-Objekts:

Cage [animals=[Cat [name=Tom], Cat[name=Felix]]]

6. Benutzerdefinierte Erwartungen

Zusätzlich zu den integrierten Erwartungen können wir mit JSpec benutzerdefinierte Erwartungen erstellen.

6.1. Unterschiedserwartung

Wir könnenDifferenceExpectation schreiben, um anzugeben, dass der Rückgabewert für die Ausführung eines Codes nicht gleich einem bestimmten Wert sein soll.

In diesem einfachen Beispiel stellen wir sicher, dass die Operation (2 + 3) nicht das Ergebnis (4) liefert:

expect(new DifferenceExpectation(4) {
    @Override
    public Integer exec() {
        return 2 + 3;
    }
});

Wir können es auch verwenden, um sicherzustellen, dass das Ausführen von Code den Status oder den Wert einer Variablen oder Methode ändert.

Wenn Sie beispielsweise ein Tier aus einemCage freisetzen, das zwei Tiere enthält, sollte die Größe unterschiedlich sein:

cage.put(tomCat, boltDog);
expect(new DifferenceExpectation(cage.size()) {
    @Override
    public Integer exec() {
        cage.release(tomCat);
        return cage.size();
    }
});

Fehlerszenario:

Hier versuchen wir, ein Tier freizulassen, das innerhalb derCage nicht existiert:

cage.release(felixCat);

Die Größe wird nicht geändert und wir erhalten die folgende Meldung:

Objects: '2' and '2' are equal, but they should not be

6.2. Ausnahme Erwartung

Wir können einExceptionExpectation schreiben, um anzugeben, dass der getestete Code einException auslösen soll.

Wir übergeben nur den erwarteten Ausnahmetyp an den Konstruktor und stellen ihn als generischen Typ bereit:

expect(new ExceptionExpectation(ArithmeticException.class) {
    @Override
    public void exec() throws ArithmeticException {
        System.out.println(1 / 0);
    }
});

Fehlerszenario Nr. 1:

System.out.println(1 / 1);

Da diese Zeile zu keiner Ausnahme führen würde, wird bei ihrer Ausführung die folgende Meldung angezeigt:

Expected exception: class java.lang.ArithmeticException, but instead got nothing

Fehlerszenario Nr. 2:

Integer.parseInt("x");

Dies würde zu einer Ausnahme führen, die sich von der erwarteten Ausnahme unterscheidet:

class java.lang.ArithmeticException,
but instead got: java.lang.NumberFormatException: For input string: "x"

7. Fazit

Andere Frameworks für fließende Zusicherungen bieten bessere Methoden für die Zusicherung von Auflistungen, Ausnahmen und die Java 8-Integration. JSpec bietet jedoch eine einzigartige Möglichkeit zum Schreiben von Zusicherungen in Form von Spezifikationen.

Es verfügt über eine einfache API, mit der wir unsere Behauptungen wie in natürlicher Sprache schreiben können, und bietet beschreibende Meldungen zu Testfehlern.

Der vollständige Quellcode für alle diese Beispiele befindet sichover on GitHub - im Paketcom.example.jspec.