IEA - Eine dateibasierte Teststrategie für Dokumententransformationen

von Douglas Campbell, leitender Ingenieur

I/E/A - Input/Erwartet/Istwert

Wenn Sie Implementierungen für den folgenden Funktionsumfang bereitstellen können,

// defines how to go from file to an instance of IN
abstract IN loadInput(File input);

// defines how to go from file to OUT instances
// throw FNF whenever there’s no expected file.
abstract OUT loadOutput(File expected) throws FileNotFoundException;

// invoked upon missing expected file or if actual != expected
abstract void storeResult(OUT result, File resultFile);

Es kann viel getan werden, um die Belastung durch das Testen von Dokumententransformationen zu verringern und einen robusten Satz von Tests aufrechtzuerhalten.

Kurz gesagt, es wird trivial, Testfälle als Dateien und nicht als Funktionen zu schreiben.

Ich bevorzuge diesen Ansatz sehr, um die Dokumententransformation zu testen, als mit Testcode zu experimentieren. Zuerst ein kleiner Hintergrund.

Hintergrund

So viel von dem Code, den ich im Laufe der Jahre geschrieben habe, hat im Kern Dokumente von einem Format in ein anderes geändert. Durch Dokumente spreche ich über jede mögliche Vielzahl von json, xml, avro, Tabulator begrenzt, yaml, was auch immer - alles und alles zu allem und alles und wieder zurück.

Als sie gefragt werden, solche Dinge zu kodieren, rollen die Augen vieler Entwickler einfach über den Schrecken, etwas so Triviales zu schreiben, wie ein Feld auf ein anderes zu mappen, es in Großbuchstaben zu schreiben, es mit einem anderen Wert zu verschmelzen, der aus einer externen Datenquelle gelesen wird, und dann in eine andere Darstellung auszugeben.

Diese neue Darstellung mag wenig Ähnlichkeit mit dem ursprünglichen Dokument haben. Das ist die Natur des Tieres.

Kurz gesagt, die Anforderungen an die Datentransformation sind völlig beliebig!

Ich denke, das ist der Grund, warum einige Entwickler dieses Zeug verabscheuen. Sie nehmen Abkürzungen und werfen Dinge in den Testcode, die so aussehen.....

//CHECKSTYLE:OFF
private static final String CLICK = "a horrendously ugly line of input from an access log";
//CHECKSTYLE:ON

Und wenn es an der Zeit ist, einen "Eindruck" zu testen, raten Sie, was passiert. Ugh - Testeingang inline als Zeichenkettenvariablen. Spidey-Sense sofort nach Unterdrückung des Checkstils aktiviert!

Eine Sache, die ich gelernt habe, ist, dass überall dort, wo es Angst und Vermeidung gibt, genau dort eine übermäßig energische Faulheit gebraucht wird. Tretet zurück. Machen Sie es sich einfach und beseitigen Sie Riese und Riese von doppelter Logik und/oder Code. Schreiben Sie eine Funktion, um einen ganzen Ordner voller Tests zu durchlaufen.

// test folder of tests and fail entire run if any fail.
public void testFolder(File testfolder, Function<IN, OUT> converter) {

    for (File test: testfolder.listFiles(testFileFilter)) {
        if (!testSingle(test, converter)) {
           fail("expected != actual - actual " +
           "results saved in .actual file");
        };
    }
}

Was ist also mit dieser testSingle-Funktion? Sehr unkompliziert mit den drei Funktionen, die zu Beginn des Blogs definiert wurden.

// test a single test
private boolean testSingle(File test, Function converter) {
    IN input = loadInput(test);
    OUT actual = converter.apply(input);
    OUT expected = null;

    // only create if no expected file or result is different.
    File actualFile = new File(test.getParent(),
                               test.getName() + ".actual");

    try {
        expected = loadOutput(new File(test.getParent(),
                                       test.getName()
                                       + ".expected"));

    } catch (FileNotFoundException ex) {
        // we haven't got expected file - no biggie
        // we can turn this into an expected file once
        // satisfied with it.
        storeResult(actual, actualFile);
    }
    return false;

    // we've got something to compare
    if (!actual.equals(expected)) {
        // fail and save the actual file for command
        // line diffing
        storeResult(actual, actualFile);
        return false;
    }

    return true;
}

Verschiedene Vorteile dieses Ansatzes

Für text- und/oder aszienbasierte Dokumente steht das Diff-Utility sofort zur Verfügung, um Testfehler zu vergleichen.

Sie müssen keinen Testcode schreiben, um zu generieren, was Ihre erwartete Ausgabe ist. Fügen Sie einfach Ihren Beispieldatensatz zum Testordner hinzu, führen Sie die Tests aus, und die eigentliche Ausgabe wird in eine neue Datei mit der Erweiterung.actual generiert.

Sie haben eine sofortige Möglichkeit, Ihren Code über Datensätze laufen zu lassen, die Ihnen Probleme in der Produktion bereitet haben. Legen Sie den problematischen Datensatz erneut in Ihren Testordner und führen Sie den Test aus.

Wenn Ihr Team beschließt, einen brandneuen Konverter zu bauen oder eine andere json-Bibliothek zu verwenden, werden alle Ihre Tests als sprachunabhängige Dateien ausgedrückt. Sie können sie vorziehen.

Alles, was man braucht, um direkt nach vorne zu kommen.

Achten Sie zunächst darauf, dass Ihre Transformationslogik zustandslos wird. Im Wesentlichen müssen Dokumenttransformationen, die außerhalb von Prozessaufrufen stattfinden, überarbeitet werden, um das Abrufen von Rohdaten von dem zu trennen, was mit ihnen gemacht wird.

Zweitens, beginnen Sie damit, dies bereits in einem frühen Stadium des Lebenszyklus von Codemodulen oder Anwendungen zu tun. Der Appetit ist normalerweise ziemlich gering, wenn es darum geht, zurückzudrehen und alte, eklige Tests zu überarbeiten.

Nächster Schritt

Ein nächster Schritt für uns ist es, dies als Open-Source-Testpaket zu verpacken. Wer weiß, es kann sogar früher passieren, wenn wir ein wenig Interesse bekommen. ?

Über ShareThis

ShareThis erschließt seit 2007 die Macht des globalen digitalen Verhaltens durch die Synthese von Social Share-, Interessen- und Absichtsdaten. Auf der Grundlage des Verbraucherverhaltens auf mehr als drei Millionen globalen Domains beobachtet ShareThis Echtzeit-Aktionen von echten Menschen auf echten digitalen Zielen.

Abonnieren Sie unseren Newsletter

Erhalten Sie die neuesten Nachrichten, Tipps und Updates

Abonnieren

Verwandte Inhalte