Best Practices für Integrationstests mit Maven?

68

Ich habe ein Projekt, das ich mit Maven baue und das Hibernate (und Spring) verwendet, um Daten aus einer Datenbank usw. abzurufen.

Meine "Tests" für die DAOs in meinem Projekt erweitern Spring's, AbstractTransactionalDataSourceSpringContextTestssodass eine DataSource mit meiner zu testenden Klasse verbunden werden kann, um die Abfrage- / Ruhezustandslogik tatsächlich ausführen, Daten abrufen usw. zu können.

Bei mehreren anderen Projekten habe ich diese Testtypen zusammen mit einer HSQL-Datenbank (entweder im Arbeitsspeicher oder auf eine Datei gerichtet) verwendet, um die tatsächliche Datenbankabfragelogik effizient testen zu können, ohne auf eine externe Datenbank angewiesen zu sein. Dies funktioniert hervorragend, da externe Abhängigkeiten vermieden werden und der "Status" der Datenbank vor dem Ausführen der Tests (von denen jeder in eine Transaktion eingeschlossen ist, die zurückgesetzt wird) genau definiert ist.

Ich bin jedoch gespannt, wie ich diese Tests, die wirklich eine lose Variante von Integrationstests darstellen, am besten mit Maven organisieren kann. Es fühlt sich ein bisschen schmutzig an, diese Tests beizubehalten src/test/java, aber nach dem, was ich gelesen habe, scheint es keine konsistente Strategie oder Praxis für die Organisation von Integrationstests mit Maven zu geben.

Nach dem, was ich bisher gelesen habe, kann ich das Failsafe-Plugin (oder eine zweite Instanz von Surefire) verwenden und an die integration-testPhase binden , und ich kann auch eine benutzerdefinierte Start- oder Herunterfahrlogik (z. B. zum Starten) binden / Stoppen der HSQL-Instanz) auf pre-integration-testoder post-integration-test. Aber ist das wirklich die beste Methode?

Meine Frage lautet also im Grunde: Was ist die allgemein anerkannte Best Practice, um dies mit Maven zu organisieren? Ich habe Probleme, eine konsistente Antwort in der Dokumentation zu finden.

Was ich möchte ist:

  • Trennen Sie Unit-Tests von Integrationstests, sodass während der testPhase nur Unit-Tests ausgeführt werden
  • Die Möglichkeit, benutzerdefinierte Start- / Herunterfahrlogik an pre-integration-testund zu bindenpost-integration-test
  • Lassen Sie die Berichte aus den Integrationstests mit den Unitfire-Surefire-Berichten zusammenführen / präsentieren
matt b
quelle
2
Verschieben Sie die Integrationstests in ein separates Projekt und behalten Sie die Komponententests im selben Projekt wie die Quelle.
Thorbjørn Ravn Andersen

Antworten:

21

Es gibt diese Codehaus-Seite mit einigen Richtlinien. Ich fand das ausfallsichere Plugin ein bisschen hackig und es macht das Ausführen der Unit-Tests in Eclipse teuflisch kompliziert. Ich mache im Großen und Ganzen, was Sie beschreiben.

Definieren Sie Integrationstests in src / itest / java. In der Phase vor dem Integrationstest:

  • Ziel- / Testklassen löschen
  • Verwenden Sie das Add-Test-Source-Ziel des Build-Helper-Maven-Plugins , um den besten Quellspeicherort hinzuzufügen
  • Verwenden Sie ein benutzerdefiniertes Mojo, um src / test / java aus der Konfiguration zu entfernen, damit die Unit-Tests nicht erneut kompiliert werden (das gefällt mir nicht wirklich, aber es ist erforderlich, um die Trennung von Unit- und Integrationstests aufrechtzuerhalten).
  • Verwenden Sie das Compiler-Plugin, um die Integrationstests zu kompilieren

Verwenden Sie dann in der Phase des Integrationstests das todsichere Plugin, um die Tests auszuführen.

Binden Sie abschließend alle Aufräumziele an die Testphase nach der Integration (obwohl sie normalerweise nicht benötigt werden, da Sie den Test Teardown () zum Aufräumen verwenden können).

Ich habe noch keine Möglichkeit gefunden, die Testergebnisse nach Ablauf der Berichtsphase zusammenzuführen, aber ich neige dazu, die Integrationstests als zusätzlichen Bonus anzusehen, solange sie den Bericht nicht so wichtig sind.

Update: Ich denke, es ist erwähnenswert, dass Sie Jetty innerhalb Ihrer Integrationstests ausführen können, anstatt ein Jetty-Ziel zu verwenden. Dies gibt Ihnen eine viel feinere Kontrolle über die Tests. Weitere Details finden Sie in dieser Antwort und in den Blogs, auf die verwiesen wird.

Reicher Verkäufer
quelle
2
Müssen Sie die Unit-Tests wirklich entfernen? Sicherlich ist es keine schlechte Idee, sie zum Zeitpunkt des Integrationstests erneut auszuführen.
Michael Rutherfurd
1
Im Allgemeinen hast du recht. Es schadet nicht, die Komponententests erneut auszuführen, aber ich habe Hunderte von Projekten auf einem Server und muss einige Optimierungen vornehmen, um die Last innerhalb der verfügbaren Hardware zu verwalten.
Rich Seller
Fair genug, Sie haben einen ziemlich wichtigen Sonderfall :-)
Michael Rutherfurd
5
Ist diese Antwort 2016 noch gültig? Sieht aus wie mvn fehlersicheres Plugin ein besserer Weg ist.
Zengr
26

Eine sehr einfache Möglichkeit hierfür ist die Verwendung von JUnit-Kategorien.

Sie können dann problemlos einige Tests während der Testphase und andere während der Integrationstestphase ausführen.

Es dauert Minuten und erfordert nur 3 Schritte.

  1. Definieren Sie eine Markierungsschnittstelle
  2. Kommentieren Sie die Klassen, die Sie teilen möchten
  3. Konfigurieren Sie Maven-Plugins.

Ein vollständiges Beispiel finden Sie hier. https://stackoverflow.com/a/10381662/1365383

John Dobie
quelle
Wenn Sie TestNG verwenden, können Sie auch Testgruppen angeben: Einheit und Integration.
Kemoda
7

Dieser gute Blog-Beitrag schlägt drei Optionen vor;

1) Separates Modul für Integrationstests

2) Verschiedene Quellverzeichnisse

3) Unterschiedliche Dateinamenmuster

Ich muss noch alle drei ausprobieren, kann also keine Meinung abgeben, die ich favorisiere.

Mike
quelle
3
Der richtige Link ist javamoods.blogspot.com/2009/12/…
Alex
1

Ich bevorzuge die zweite Option, Verschiedene Quellverzeichnisse, aber ich fand es ziemlich ärgerlich, mit der IT die Integrationstests beenden oder Pakete ausschließen zu müssen.

Um dies zu vermeiden, habe ich folgende Konfiguration erhalten:

<properties>
    <testSource>src/test/java</testSource>
    <testSourceResource>src/test/resources</testSourceResource>
</properties>
<build>
    <testSourceDirectory>${testSource}</testSourceDirectory>
    <testResources>
            <testResource>
            <directory>${testSourceResource}</directory>
            </testResource>
        </testResources>
.....
.....

und dann überschreibe ich beide Variablen in verschiedenen Profilen für den Integrations- und Abnahmetest:

<profiles>
  <profile>
   <id>acceptance-tests</id>
   <properties>
    <testSource>src/acceptance-test/java</testSource>
    <testSourceResource>src/acceptance-test/resources</testSourceResource>
   </properties>
  </profile>
 <profile>
   <id>integration-tests</id>
    <properties>
    <testSource>src/integration-test/java</testSource>
    <testSourceResource>src/integration-test/resources</testSourceResource>
    </properties>
  </profile>
.....
.....
.....
Pablo Gutierrez
quelle