Wie kann ich meine Maven-Integrationstests ausführen?

170

Ich habe ein maven2-Multimodulprojekt und in jedem meiner untergeordneten Module habe ich JUnit-Tests, die benannt sind, Test.javaund Integration.javafür Komponententests bzw. Integrationstests. Wenn ich ausführe:

mvn test

Alle JUnit-Tests *Test.javain den untergeordneten Modulen werden ausgeführt. Wenn ich ausführe

mvn test -Dtest=**/*Integration

Keiner der Integration.javaTests wird in den untergeordneten Modulen ausgeführt.

Diese scheinen mir genau der gleiche Befehl zu sein, aber der mit der -Dtest = / * Integration ** funktioniert nicht. Er zeigt 0 Tests an, die auf der übergeordneten Ebene ausgeführt werden, für die es keine Tests gibt

Peter Delaney
quelle
4
Kiefs Antwort sollte die akzeptierte sein, da dies der aktuelle Standard für die Definition von Integrationstests in Maven ist.
Heenenee

Antworten:

110

Sie können Maven's Surefire so einrichten, dass Unit-Tests und Integrationstests separat ausgeführt werden. In der Standard-Unit-Test-Phase führen Sie alles aus, was nicht mit einem Integrationstest übereinstimmt. Anschließend erstellen Sie eine zweite Testphase , in der nur die Integrationstests ausgeführt werden.

Hier ist ein Beispiel:

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-surefire-plugin</artifactId>
      <configuration>
        <excludes>
          <exclude>**/*IntegrationTest.java</exclude>
        </excludes>
      </configuration>
      <executions>
        <execution>
          <id>integration-test</id>
          <goals>
            <goal>test</goal>
          </goals>
          <phase>integration-test</phase>
          <configuration>
            <excludes>
              <exclude>none</exclude>
            </excludes>
            <includes>
              <include>**/*IntegrationTest.java</include>
            </includes>
          </configuration>
        </execution>
      </executions>
    </plugin>
serg10
quelle
1
Ich habe dies wie gesagt konfiguriert und nur die * Test nicht die * Integration.java-Dateien werden ausgeführt, wenn Folgendes ausgeführt wird: mvn install Ich muss meine * Test.java als Standard ausführen, aber für meinen nächtlichen Build muss ich beide * Test ausführen .java und * Integration.java. Ich muss mvn install dann cd in jedes untergeordnete Verzeichnis ausführen und mvn -Dtest = ** / * Integrationstest
Peter Delaney
66
Sie sollten das Fail-Safe-Plugin für Integrationstests verwenden, nicht das Safe-Fire-Plugin. Der Build wird erst nach Abschluss der Phase nach der Integration fehlschlagen . So können Sie Testressourcen (z. B. einen Webserver) herunterfahren, bevor der Build fehlschlägt. Daher ausfallsicher.
John Gordon
Für mich startet der Stegserver im Rahmen der Vorintegrationsphase. Die letzte Protokollzeile lautet: [INFO] Jetty Server gestartet. Danach passiert nichts mehr. Es bleibt stecken. Das ausfallsichere Maven Surefire-Plugin führt keine Tests aus und der Steg-Server stoppt nicht. Irgendeine Idee, was los ist? Ich verwende dieselbe Konfiguration wie von Ihnen angegeben.
Tarun Kumar
6
Diese Antwort ist sehr veraltet und sollte aktualisiert oder entfernt werden.
Zac Thompson
Irgendeine Hilfe bei diesem? stackoverflow.com/questions/48639730/…
Rohit Barnwal
250

Der Maven-Build-Lebenszyklus enthält jetzt die Phase "Integrationstest" zum Ausführen von Integrationstests, die getrennt von den Unit-Tests ausgeführt werden, die während der "Test" -Phase ausgeführt werden. Es wird nach "package" ausgeführt. Wenn Sie also "mvn verify", "mvn install" oder "mvn deploy" ausführen, werden auf dem Weg Integrationstests ausgeführt.

Standardmäßig wird die Integration-Test Testklassen genannt **/IT*.java, **/*IT.javaund **/*ITCase.java, aber das konfiguriert werden kann.

Einzelheiten dazu, wie Sie dies alles verkabeln können, finden Sie im Failsafe-Plugin , auf der Failsafe-Verwendungsseite (nicht korrekt von der vorherigen Seite verlinkt, während ich dies schreibe) sowie in diesem Sonatype-Blogbeitrag .

Kief
quelle
1
@ WillV Richtig. Der Friedhof des Codehauses. Und das Maven-Failsafe-Plugin ist jetzt in Apache. Es tut uns leid. :)
Jin Kwon
38
Standardmäßig werden mvn integration-testauch Komponententests ausgeführt (mithilfe von Surefire), es werden jedoch mvn failsafe:integration-testnur die ausfallsicheren Integrationstests ausgeführt.
Shadow Man
22
Unglaublicherweise wird in der Dokumentation zum Failsafe-Plugin, auf der Verwendungsseite und in den häufig gestellten Fragen nicht erwähnt, dass Testklassen mit den Namen * / IT .java, ** / * IT.java und ** / * ITCase.java ausgeführt werden ...
Henno Vermeulen
1
Wenn es nach läuft packagePhase, das heißt , sollte ich alle meine IT Java - Quellcode unter setzen , src/main/javaanstatt src/test/javarichtig?
Bruce Sun
5
@HennoVermeulen Ich war verwirrt darüber, wie ich Tests nennen soll. Es ist in Einschlüsse und Ausschlüsse von Tests beschrieben . Es ist schön, dass die Standardeinstellungen überschrieben werden können, aber es wäre schön, wenn sie die Standardeinstellungen früher erwähnen würden.
Joshua Taylor
63

Ich habe genau das getan, was Sie tun möchten, und es funktioniert großartig. Komponententests "* Tests" werden immer ausgeführt, und "* IntegrationTests" werden nur ausgeführt, wenn Sie eine MVN-Überprüfung oder MVN-Installation durchführen. Hier ist es der Ausschnitt aus meinem POM. serg10 hatte es fast richtig .... aber nicht ganz.

  <plugin>
    <!-- Separates the unit tests from the integration tests. -->
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
       <!-- Skip the default running of this plug-in (or everything is run twice...see below) -->
       <skip>true</skip>
       <!-- Show 100% of the lines from the stack trace (doesn't work) -->
       <trimStackTrace>false</trimStackTrace>
    </configuration>
    <executions>
       <execution>
          <id>unit-tests</id>
          <phase>test</phase>
          <goals>
             <goal>test</goal>
          </goals>
          <configuration>
                <!-- Never skip running the tests when the test phase is invoked -->
                <skip>false</skip>
             <includes>
                   <!-- Include unit tests within integration-test phase. -->
                <include>**/*Tests.java</include>
             </includes>
             <excludes>
               <!-- Exclude integration tests within (unit) test phase. -->
                <exclude>**/*IntegrationTests.java</exclude>
            </excludes>
          </configuration>
       </execution>
       <execution>
          <id>integration-tests</id>
          <phase>integration-test</phase>
          <goals>
             <goal>test</goal>
          </goals>
          <configuration>
            <!-- Never skip running the tests when the integration-test phase is invoked -->
             <skip>false</skip>
             <includes>
               <!-- Include integration tests within integration-test phase. -->
               <include>**/*IntegrationTests.java</include>
             </includes>
          </configuration>
       </execution>
    </executions>
  </plugin>

Viel Glück!

HDave
quelle
Genau das, was ich versucht habe, aber meine Integrationstests wurden während der MVN-Testphase fortgesetzt, da ich den Standard NICHT übersprungen habe. Ich dachte, die Konfiguration der Testausführung würde sie überschreiben. Wie Sie erklärt haben, wird lediglich eine neue Ausführung hinzugefügt (daher würde alles zweimal ausgeführt). Für mich fehlte also das Überspringen. +1 Da diese Konfiguration die Frage zu 100% beantwortet
Nils Schmidt
2
Dann können Sie das Kontrollkästchen aktivieren, damit diese Antwort die Antwort ist!
HDave
Für mich startet der Stegserver im Rahmen der Vorintegrationsphase. Die letzte Protokollzeile lautet: [INFO] Jetty Server gestartet. Danach passiert nichts mehr. Es bleibt stecken. Das ausfallsichere Maven Surefire-Plugin führt keine Tests aus und der Steg-Server stoppt nicht. Irgendeine Idee, was los ist? Ich verwende dieselbe Konfiguration wie von Ihnen angegeben.
Tarun Kumar
@ Tarun - stellen Sie eine neue Frage zu Ihrem Problem
HDave
2
Dies sollte die akzeptierte Antwort sein. Das damit verbundene Maven-Ziel ist:clean compile integration-test -Dmaven.test.failure.ignore=false
Neill Lima
31

Sie können sie sehr einfach mit JUnit-Kategorien und Maven aufteilen.
Dies wird im Folgenden sehr, sehr kurz durch Aufteilen von Einheiten- und Integrationstests gezeigt.

Definieren Sie eine Marker-Schnittstelle

Der erste Schritt beim Gruppieren eines Tests anhand von Kategorien besteht darin, eine Markierungsschnittstelle zu erstellen.
Diese Schnittstelle wird verwendet, um alle Tests, die Sie ausführen möchten, als Integrationstests zu markieren.

public interface IntegrationTest {}

Markieren Sie Ihre Testklassen

Fügen Sie die Kategorieanmerkung oben in Ihrer Testklasse hinzu. Es nimmt den Namen Ihrer neuen Schnittstelle an.

import org.junit.experimental.categories.Category;

@Category(IntegrationTest.class)
public class ExampleIntegrationTest{

    @Test
    public void longRunningServiceTest() throws Exception {
    }

}

Konfigurieren Sie Maven Unit Tests

Das Schöne an dieser Lösung ist, dass sich für den Unit-Test nichts wirklich ändert.
Wir fügen dem Maven Surefire-Plugin einfach eine Konfiguration hinzu, damit Integrationstests ignoriert werden.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.11</version>
    <configuration>
        <includes>
            <include>**/*.class</include>
        </includes>
        <excludedGroups>
            com.test.annotation.type.IntegrationTest
        </excludedGroups>
    </configuration>
</plugin>

Wenn Sie a mvn clean testausführen, werden nur Ihre nicht markierten Komponententests ausgeführt.

Konfigurieren Sie Maven-Integrationstests

Auch hier ist die Konfiguration sehr einfach.
Wir verwenden das ausfallsichere Standard-Plugin und konfigurieren es so, dass nur die Integrationstests ausgeführt werden.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.19.1</version>
    <configuration>
        <includes>
            <include>**/*.class</include>
        </includes>
        <groups>
            com.test.annotation.type.IntegrationTest
        </groups>
    </configuration>
</plugin>

Die Konfiguration verwendet ein Standardausführungsziel, um das ausfallsichere Plugin während der Integrationstestphase des Builds auszuführen.

Sie können jetzt eine mvn clean install.
Dieses Mal werden neben den laufenden Unit-Tests auch die Integrationstests während der Integrationstestphase ausgeführt.

John Dobie
quelle
Ich dachte, JUnit hat keine Geheimnisse mehr für mich. Gute Stelle!
Gertas
4
Dies funktioniert nur, wenn die Markierungsschnittstelle bereits an einem für Maven verfügbaren Ort vorhanden ist. Es funktioniert nicht, wenn Ihre Markierungsschnittstelle in einem anderen Modul desselben Builds mit mehreren Modulen vorhanden ist.
EngineerBetter_DJ
@EngineerBetter_DJ was meinst du damit? Sie können das nicht tun, wenn Sie eine auf mehreren Projekten basierende Maven-Konfiguration haben?
Matieieusb
16

Sie sollten versuchen, das ausfallsichere Maven-Plugin zu verwenden . Sie können festlegen, dass bestimmte Tests enthalten sein sollen.

James Kingsbery
quelle
1
+1 Das benutze ich. Funktioniert gut und ermöglicht Ihnen die Einrichtung vor / nach dem Einrichten, z. B. das Starten und Herunterfahren eines lokalen Servlet-Containers.
Mdma
maven-failsafe-pluginist zu Plugin Graveyard
Jin Kwon
9
Auf der Friedhofsseite steht nur, dass das failsafePlugin verschoben wurde maven-failsafe-plugin. Es sieht so aus, als ob das maven-failsafe-pluginnoch aktiv ist (Dokumente wurden zuletzt im März 2014 gepusht).
James Kingsbery
13

Standardmäßig führt Maven nur Tests aus, deren Klassenname Test enthält.

Benennen Sie in IntegrationTest um und es wird wahrscheinlich funktionieren.

Alternativ können Sie die Maven-Konfiguration ändern, um diese Datei einzuschließen, aber es ist wahrscheinlich einfacher und besser, nur Ihre Tests SomethingTest zu nennen.

Aus Ein- und Ausschlüssen von Tests :

Standardmäßig enthält das Surefire-Plugin automatisch alle Testklassen mit den folgenden Platzhaltermustern:

  • \*\*/Test\*.java - Enthält alle Unterverzeichnisse und alle Java-Dateinamen, die mit "Test" beginnen.
  • \*\*/\*Test.java - enthält alle Unterverzeichnisse und alle Java-Dateinamen, die mit "Test" enden.
  • \*\*/\*TestCase.java - enthält alle Unterverzeichnisse und alle Java-Dateinamen, die mit "TestCase" enden.

Wenn die Testklassen nicht der Namenskonvention entsprechen, konfigurieren Sie das Surefire-Plugin und geben Sie die Tests an, die Sie einschließen möchten.

Cletus
quelle
Hallo und danke, ich habe zwei Arten von Tests, normale POJO Junit-Tests namens SomethingTest.java, die ausgelöst werden. Ich habe auch Integrationstests namens SomethingIntegration.java, die nicht ausgelöst werden. Die Datei SomethingTest.java wird per MVN-Test oder MVN-Installation ausgelöst. Die zweiten Tests werden nicht ausgelöst. mvn test -Dtest = ** / * Integration
Peter Delaney
.. und mit "Maven führt nur Tests aus, deren Test irgendwo im Klassennamen steht" meinen Sie "das Maven-todsichere Plugin führt nur Tests aus, deren Test irgendwo im Klassennamen steht".
Joshua Davis
1
Es ist nicht "irgendwo im Klassennamen", sondern "der Klassenname endet mit Test", zum Beispiel funktioniert MyTest, MyTests jedoch nicht
Julian
10

Eine andere Möglichkeit, Integrationstests mit Maven durchzuführen, besteht darin, die Profilfunktion zu verwenden:

...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <includes>
                    <include>**/*Test.java</include>
                </includes>
                <excludes>
                    <exclude>**/*IntegrationTest.java</exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

<profiles>
    <profile>
        <id>integration-tests</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <includes>
                            <include>**/*IntegrationTest.java</include>
                        </includes>
                        <excludes>
                            <exclude>**/*StagingIntegrationTest.java</exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>
...

Wenn Sie 'mvn clean install' ausführen , wird der Standard-Build ausgeführt. Wie oben angegeben, werden Integrationstests ignoriert. Das Ausführen von 'mvn clean install -P Integrationstests' umfasst die Integrationstests (ich ignoriere auch meine Staging-Integrationstests). Außerdem habe ich einen CI-Server, der jede Nacht meine Integrationstests ausführt und dafür den Befehl 'mvn test -P Integrationstests' ausführe .

Jorge
quelle
1
Warum würden Sie die Integrationstestphase nicht nutzen? Profile können dann beispielsweise für Integrationstests gegen verschiedene App-Server usw. verwendet werden, wie dies bei Arquillian der Fall ist. Ich bin kein Maven-Experte, aber ich denke, die Experten könnten sagen, dass dies nicht sehr 'Maven-y' ist.
Joshua Davis
1
@Joshua Ich denke, ich mache das so, weil meine Integrationstests mindestens 5 Minuten dauern und ich mehrmals am Tag 'mvn clean install' ausgeben muss, weil ich meine Artefakte in meinem lokalen Maven-Repo aktualisieren muss. Nach den obigen Aussagen führt das Ausführen von "Installieren" dazu, dass die Integrationstestphase ausgeführt wird, wodurch ich wertvolle Entwicklerzeit verliere.
Jorge
Hmm ... ich bin mir nicht sicher, ob ich den Integrationstest installieren soll. In jedem Fall würde ich immer noch die Phase anstelle eines Profils verwenden. Profile sind besser geeignet, um beispielsweise verschiedene App-Server zu unterstützen usw.
Joshua Davis
1
Ich werde dann weitermachen und damit herumspielen. Danke für den Hinweis!
Jorge
@jorge Ich denke, das richtige Ziel wäre hier zu überprüfen, oder?
Kilokahn
1

Sie können der Maven-Dokumentation folgen, um die Komponententests mit dem Build auszuführen und die Integrationstests separat auszuführen.

<project>
    <properties>
        <skipTests>true</skipTests>
    </properties>
    [...]
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.20.1</version>
                <configuration>
                    <skipITs>${skipTests}</skipITs>
                </configuration>
            </plugin>
        </plugins>
    </build>
    [...]
</project>

Auf diese Weise können Sie alle Integrationstests ausführen, die standardmäßig deaktiviert sind. Um sie auszuführen, verwenden Sie diesen Befehl:

mvn install -DskipTests=false
Dherik
quelle
0

Sie sollten das Maven Surefire-Plugin verwenden , um Unit-Tests auszuführen, und das Maven Failsafe-Plugin , um Integrationstests auszuführen.

Bitte folgen Sie unten, wenn Sie die Ausführung dieser Tests mithilfe von Flags umschalten möchten.

Maven-Konfiguration

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <skipTests>${skipUnitTests}</skipTests>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-failsafe-plugin</artifactId>
            <configuration>
                <includes>
                    <include>**/*IT.java</include>
                </includes>
                <skipTests>${skipIntegrationTests}</skipTests>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>integration-test</goal>
                        <goal>verify</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

        <properties>
            <skipTests>false</skipTests>
            <skipUnitTests>${skipTests}</skipUnitTests>
            <skipIntegrationTests>${skipTests}</skipIntegrationTests>
        </properties>

Daher werden Tests gemäß den folgenden Flaggenregeln übersprungen oder umgeschaltet:

Tests können durch folgende Flags übersprungen werden:

  • -DskipTests Überspringt sowohl Unit- als auch Integrationstests
  • -DskipUnitTests Überspringt Unit-Tests, führt jedoch Integrationstests aus
  • -DskipIntegrationTests Überspringt Integrationstests, führt jedoch Komponententests aus

Ausführen von Tests

Führen Sie unten aus, um nur Unit-Tests auszuführen

mvn clean test

Sie können den folgenden Befehl ausführen, um die Tests auszuführen (sowohl Einheit als auch Integration).

mvn clean verify

Befolgen Sie die Anweisungen, um nur Integrationstests auszuführen

mvn failsafe:integration-test

Oder überspringen Sie Unit-Tests

mvn clean install -DskipUnitTests

Um Integrationstests während zu überspringen mvn install, folgen Sie außerdem

mvn clean install -DskipIntegrationTests

Sie können alle Tests mit überspringen

mvn clean install -DskipTests
Liquidpie
quelle