JUnit Supplementary Classes

fastjack

Top Contributor
Ich habe zwei Codestücke gesehen. Beim ersten habe eine Testklasse und eine Testobjektfactory:

Java:
class PersonTest {
    private Person person = PersonTestFactory.create();
    private Person personWithNoCity = PersonTestFactory.withNoCity();
    @Test
    public void shouldHaveExpectedName() {
        assertEquals("bundy", this.person.getName());
    }
    @Test
    public void shouldHaveNoCity() {
        assertEquals("", this.person.getCity());
    }
    ...
}

class PersonTestFactory {
    static Person create() {
        Person person = new Person();
        person.setName("bundy");
        person.setFirstName("al");
        person.setCity("Entenhausen");
        return person;
    }
    static Person withNoCity() {
        Person person = create();
        person.setCity("");
        return person;
    }
}

Bei diesem Code werden feste Testobjekte durch TestFactories erzeugt. Die Testobjekte können wiederverwendet werden und haben dann immer den gleichen Namen, Vornamen usw. Ich habe wenig Änderungsaufwand, wenn zur Person noch ein Feld dazu kommt bzw. ändert, da die Objekterzeugung an einer zentralen Stelle ist.

Das zweite Codestück wäre z.B.:
Java:
class PersonTest {
    @Test
    public void shouldHaveExpectedName() {
        Person person = new Person();
        person.setName("bundy");
        assertEquals("bundy", person.getName());
    }
    @Test
    public void shouldHaveNoCity() {
        Person person = new Person();
        person.setName("bundy");
        person.setCity("");
        assertEquals("", person.getCity());
    }
    ...
}
Testobjekte werden in den Tests erzeugt, können immer anders aussehen. Hier kann schnell die übersicht flöten gehen, Personen können in anderen Test komplett anders aussehen usw.

Ich bin geteilter Meinung. Was haltet ihr davon? Wo seht Ihr Vorteile und Nachteile?
 
Zuletzt bearbeitet:
Sowas kannst du nur bedingt pauschalisieren. Im Grunde sind wir Programmierer ja ein faules Volk. Sprich wir vereinfachen wo es nur geht. Grundsätzlich ist es eine Sache, die ich auch persönlich für Tests einsetze und sehr zu schätzen gelernt habe. Nur muss man von Fall zu Fall abschätzen, ob sich der Aufwand für die Factory lohnt, wenn du eh nur 2 oder 3 mal die Factory benutzen musst im Test.
 
Bei diesem Code werden feste Testobjekte durch TestFactories erzeugt.
Da ist schon mal sehr gut, wie du selebr sagst musst du nur an zentralen Stellen ändern, wichtig wenn man viele Tests hat, wie zB. bei TDD oder hoher Testabdeckung. Allerdings sehe ich da ein paar Problem beim Test selber:
Java:
    @Test
    public void shouldHaveExpectedName() {
        assertEquals("bundy", this.person.getName());
    }
"bundy" ist ja wohl sehr magisch und dadurch veschleiernd, den test vesteht man so nicht, aber "bundy" ist auch noch redundant.

Es gibt grundsätzlich 2 Arten von Testobjekten (mal von mocks/Stubs/Fakes agesheen):
Solche, bei denen man die Werte kennt, und solche bei denen man die Werte nicht kennt (Anonym).

Da lohnen sich grundsätzlich 2 Arten von Test Objekt Factories: Solche, denen man Werte mitgibt, und solche, die anonyme Testdaten nutzen.
Leider mischt dein 1. Test beide Arten, es wird zwar etwas anonymes erzeugt, aber dann auf einen bestimmten Wert geprüft.
Geprüft wird übrigens da nur die Factory, sonst nix 😉

Übrigens, CustomAsserts sind eine gute Sache, einmal um redundanz zu vermeiden, dann noch um Klarheit zu schaffen, falls du öfters auf den namen prüfst, wäre ein [c]assertPersonNameEquals(String expected, Person actual)[/c] nicht verkehrt.

Lesetipp: XUnit Test Patterns : Refactoring Test Code
 
Geprüft wird übrigens da nur die Factory

Darum war ich geteilter Meinung. Wenn dort bei den Settern etwas schief läuft, wird es vielleicht schwer die richtige Stelle zu finden... Wie kann man das anders machen? Was meinst Du mit anonymen Testdaten?
 
Die factories Testen ist sicherlich keine schlechte Idee, dachte zuerst es sollte etwas echtes getestet werden 😉

Was meinst Du mit anonymen Testdaten?
Damit meine ich testdaten die für den test irrelevant sind und daher "anonym" sein können, sie mit in den Test aufzunehmen bringt keine zus. Abddeckung oder sonstige Vorteile, da wird nur der eigentliche Test komplizierter und dadurch mehr verschleiert als nötig.

Stell dir vor du möchtest die City Logik testen(wenn es denn eine gäbe), da ist der Name der Person doch egal, oder? 😉
Wenn du beim erzeugen der Person immer den Namen mitangibst, könntest du auch "blablubb" angeben und es wäre egal, der Leser des Tests allerdings wundert sich.
Nimmst du eine Variable/Konstante die nur heisst [c]anonymousName[/c], [c]randomName[/c], oder gleich FactoryMethoden wie [c]createPersonWithCityAndRadomName[/c] (übertrieben) weiss der Leser eher worauf er achten muss.
Es gibt auch Frameworks die einem zufällige TEstdaten erzeugen: Generate Test Data with DataFactory | Javalobby
Sind natürlich nur dann geeignet wenn die Daten auch nicht abgeprüft werden, also anonym sind.
 

Zurück
Oben