Java >> Java Tutorial >  >> Java

Tests für Datenzugriffscode schreiben – Green Build ist nicht gut genug

Das erste, was wir tun müssen, bevor wir mit dem Schreiben von Integrationstests für unseren Datenzugriffscode beginnen können, ist zu entscheiden, wie wir unsere Testfälle konfigurieren werden.

Wir haben zwei Möglichkeiten:die richtige und die falsche.

Leider treffen viele Entwickler die falsche Wahl.

Wie können wir vermeiden, denselben Fehler zu machen?

Wir können die richtigen Entscheidungen treffen, indem wir diese drei Regeln befolgen:

Regel 1:Wir müssen unsere Anwendung testen

Diese Regel scheint offensichtlich. Leider verwenden viele Entwickler eine andere Konfiguration in ihren Integrationstests, weil sie ihre Tests bestehen lässt.

Das ist ein Fehler!

Diese Frage sollten wir uns stellen:

Wollen wir testen, ob unser Datenzugriffscode funktioniert, wenn wir die Konfiguration verwenden, die in der Produktionsumgebung verwendet wird, oder wollen wir nur, dass unsere Tests bestehen?

Ich denke, dass die Antwort offensichtlich ist. Wenn wir in unseren Integrationstests eine andere Konfiguration verwenden, testen wir nicht, wie sich unser Datenzugriffscode in der Produktionsumgebung verhält. Wir testen, wie es sich verhält, wenn wir unsere Integrationstests ausführen.

Mit anderen Worten, wir können nicht überprüfen, ob unser Datenzugriffscode wie erwartet funktioniert, wenn wir unsere Anwendung in der Produktionsumgebung bereitstellen.

Klingt das nach einem würdigen Ziel?

Wenn wir testen möchten, ob unser Datenzugriffscode funktioniert, wenn wir die Produktionskonfiguration verwenden, sollten wir diese einfachen Regeln befolgen:

  • Wir sollten unsere Tests konfigurieren, indem wir dieselbe Konfigurationsklasse oder Konfigurationsdatei verwenden, die die Persistenzschicht unserer Anwendung konfiguriert.
  • Unsere Tests sollten dasselbe Transaktionsverhalten verwenden wie unsere Anwendung.

Diese Regeln haben zwei große Vorteile:

  1. Da unsere Integrationstests genau dieselbe Konfiguration wie unsere Anwendung und dasselbe Transaktionsverhalten verwenden, helfen uns unsere Tests zu überprüfen, ob unser Datenzugriffscode wie erwartet funktioniert, wenn wir unsere Anwendung in der Produktionsumgebung bereitstellen.
  2. Wir müssen keine unterschiedlichen Konfigurationen pflegen. Mit anderen Worten, wenn wir eine Änderung an unserer Produktionskonfiguration vornehmen, können wir testen, ob die Änderung nichts beschädigt, ohne Änderungen an der Konfiguration unserer Integrationstests vorzunehmen.

Regel 2:Wir können Regel 1 brechen

Es gibt keine universellen Wahrheiten in der Softwareentwicklung. Jede Grundsatzregel gilt nur unter bestimmten Bedingungen. Wenn sich die Bedingungen ändern, müssen wir diese Grundsätze neu bewerten. Dies gilt auch für die erste Regel.

Es ist ein guter Ausgangspunkt, aber manchmal müssen wir es brechen.

Wenn wir eine testspezifische Änderung an unserer Konfiguration vornehmen möchten, müssen wir diesen Schritten folgen:

  1. Finden Sie den Grund für die Änderung heraus.
  2. Listen Sie die Vor- und Nachteile der Änderung auf.
  3. Wenn die Vorteile die Nachteile überwiegen, dürfen wir die Konfiguration unserer Tests ändern.
  4. Dokumentieren Sie den Grund für diese Änderung. Dies ist entscheidend, weil es uns die Möglichkeit gibt, diese Änderung rückgängig zu machen, wenn wir herausfinden, dass es eine schlechte Idee war, sie vorzunehmen.

Beispielsweise möchten wir unsere Integrationstests gegen eine In-Memory-Datenbank ausführen, wenn diese Tests in einer Entwicklungsumgebung (auch bekannt als PC des Entwicklers) ausgeführt werden, da dies die Feedback-Schleife verkürzt. Der einzige Nachteil dieser Änderung besteht darin, dass wir nicht 100 % sicher sein können, dass unser Code in der Produktionsumgebung funktioniert, da er eine echte Datenbank verwendet.

Dennoch überwiegen die Vorteile dieser Änderung die Nachteile, da wir unsere Integrationstests immer noch gegen eine echte Datenbank ausführen können (und sollten). Eine gute Möglichkeit, dies zu tun, besteht darin, unseren CI-Server für die Ausführung dieser Tests zu konfigurieren.

Dies ist natürlich ein sehr einfaches (und vielleicht etwas naives) Beispiel, und oft sind die Situationen, mit denen wir konfrontiert sind, viel komplizierter. Deshalb sollten wir diese Richtlinie befolgen:

Im Zweifelsfall Testkonfiguration weglassen.

Regel 3:Wir dürfen keine transaktionalen Integrationstests schreiben

Einer der gefährlichsten Fehler, den wir machen können, besteht darin, das Transaktionsverhalten unserer Anwendung in unseren Integrationstests zu ändern.

Wenn wir unsere Tests transaktional machen, ignorieren wir die Transaktionsgrenze unserer Anwendung und stellen sicher, dass der getestete Code innerhalb einer Transaktion ausgeführt wird. Dies ist äußerst schädlich, da es uns nur hilft, mögliche Fehler zu verbergen, anstatt sie aufzudecken.

Einmal mehr müssen wir uns diese Frage stellen:

Wollen wir testen, ob unser Datenzugriffscode funktioniert, wenn wir die Konfiguration verwenden, die in der Produktionsumgebung verwendet wird, oder wollen wir nur, dass unsere Tests bestehen?

Und wieder einmal liegt die Antwort auf der Hand.

Zusammenfassung

Dieser Blogbeitrag hat drei Dinge gelehrt:

  • Unser Ziel ist es nicht zu überprüfen, ob unser Datenzugriffscode korrekt funktioniert, wenn wir unsere Tests durchführen. Unser Ziel ist sicherzustellen, dass es ordnungsgemäß funktioniert, wenn unsere Anwendung in der Produktionsumgebung bereitgestellt wird.
  • Jede testspezifische Änderung erzeugt einen Unterschied zwischen unserer Testkonfiguration und der Produktionskonfiguration. Wenn dieser Unterschied zu groß ist, sind unsere Tests nutzlos.
  • Transaktionsintegrationstests sind schädlich, weil sie das Transaktionsverhalten unserer Anwendung ignorieren und Fehler verbergen, anstatt sie aufzudecken.

Das ist eine ziemlich schöne Zusammenfassung. Wir haben diese Dinge tatsächlich gelernt, aber wir haben auch etwas viel Wichtigeres gelernt. Das Wichtigste, was wir aus diesem Blogpost gelernt haben, ist diese Frage:

Wollen wir testen, ob unser Datenzugriffscode funktioniert, wenn wir die Konfiguration verwenden, die in der Produktionsumgebung verwendet wird, oder wollen wir nur, dass unsere Tests bestehen?

Wenn wir diese Frage immer wieder stellen, sollte uns der Rest klar sein.


Java-Tag