Unit- und Integration-Test eines MicroService mit Maven

Was ist ein MicroService? In unserem Kontext ist es ein (kleines) Modul der Gesamtanwendung, welches seinen Dienst als Webapplikation (.war) anbietet. Das konkrete Schnittstellen-Protokoll ist für diesen Artikel nicht entscheidend. Möglich ist klassisch SOAP, REST aber auch Spring HttpInvoker. Ein MicroService ist eine gute Möglichkeit Sollbruchstellen in die Gesamtanwendung einzubauen.

Nun zum eigentlichen Thema: Wie teste ich einen solchen Service? Im Grunde wie immer, d.h. viele Unit-Tests und ein paar ausgewählte Integration-Tests. Die Integration-Tests sollen zeigen, dass die angebotenen Schnittstellen des Services funktionieren und alles richtig konfiguriert ist. Die Integration-Tests, die die Gesamtanwendung, d.h. das Netz aller Services testet, ist hier nicht Bestandteil.

Wie macht man das jetzt mit Maven? Eine Variante ist die Unit-Tests und Integration-Tests zu trennen. Vor der integration-test Phase einen Tomcat zu starten, dann seine Integration-Tests auszuführen und anschließend wieder den Tomcat zu stoppen. Tomcat, weil wir diesen nicht nur lokal einsetzen und somit “gleicher” zur Produktion sind. Eine echte Plugin-Auswahl fand nicht statt, wir sind einfach mit dem tomcat7-maven-plugin gestartet.

Mit Maven Tomcat automatisch starten und stoppen

  <build>
    <plugins>
      ..
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.0-beta-1</version>
        <configuration>
          <contextFile>${project.basedir}/src/test/resources/test-context.xml</contextFile>
        </configuration>
        <executions>
          <execution>
            <id>tomcat-run</id>
            <goals>
              <goal>run-war-only</goal>
            </goals>
            <phase>pre-integration-test</phase>
            <configuration>
              <fork>true</fork>
            </configuration>
          </execution>
          <execution>
            <id>tomcat-shutdown</id>
            <goals>
              <goal>shutdown</goal>
            </goals>
            <phase>post-integration-test</phase>
          </execution>
        </executions>
      </plugin>

    </plugins>
  </build>

Das Starten des Tomcats binden wir an die pre-integration-test Phase (Zeile 17). Wichtig ist fork auf true zu setzen (Zeile 19), da sonst Maven nach Start des Tomcats stehen bleibt. Das Beenden binden wir entsprechend an die post-integration-test Phase (Zeile 27). Wenn keine context.xml in der webapp enthalten ist, muss eine per contextFile angeben werden (Zeile 9).

So, unser Tomcat startet und stoppt nun beim Ausführen von mvn integration-test.

Mit Maven innerhalb eines Modules Unit- und Integration-Tests trennen

Nächster Schritt ist die Unit- und Integration-Tests zu trennen. Im Netz empfehlen einige dies in separaten Maven-Modulen zu tun. Wir finden es sinnvoller dies über die Test-Phasen zu steuern:

  <build>
    <plugins>
      ..
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
          <skip>true</skip>
          <trimStackTrace>false</trimStackTrace>
        </configuration>
        <executions>
          <execution>
            <id>unit-tests</id>
            <phase>test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <skip>false</skip>
              <includes>
                <include>**/*Test.java</include>
              </includes>
              <excludes>
                <exclude>**/*IntegrationTest.java</exclude>
              </excludes>
            </configuration>
          </execution>
          <execution>
            <id>integration-tests</id>
            <phase>integration-test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <skip>false</skip>
              <includes>
                <include>**/*IntegrationTest.java</include>
              </includes>
            </configuration>
          </execution>
        </executions>
      </plugin>

    </plugins>
  </build>

In Zeile 8 wird das Default-Test-Verhalten vom maven-surefire-plugin ausgeschaltet. Durch zwei einzelne <execution/>'s können wir unterschiedliche <configuration/>'s an unterschiedliche Phasen binden (Zeile 14 und 30). In der test Phase werden alle Klassen mit Endung Test.java ausgeführt außer jene mit Endung IntegrationTest.java. In der integration-test Phase werden nun lediglich alle Klassen mit Endung IntegrationTest.java ausgeführt. Vielen Dank an HDave, der letzteres auf Stackoverflow schön erklärt.

Hast du ähnliche Anwendungsfälle? Wie hast du diese gelöst?

JUG BB am 12.10. – Fighting Layout Bugs

Am Mittwoch 12.10. wird Michael Tamm bei uns in der Klosterstrasse 71 einen spannenden Vortrag zum Thema „Fighting Layout Bugs“ halten.

Um was geht’s in dem Vortrag:
Für die “normale” Programmierung gibt es Unit Tests. Aber wie können automatische Tests für die Arbeit von HMTL- und CSS-Programmierern aussehen? Wie kann man sicherstellen, dass jede Webseite so aussieht, wie es sich der Designer vorgestellt hat? Wie können automatische Tests für Layoutfehler aussehen? Der Vortrag beantwortet
genau diese Fragen: Es werden mehrere typische Layoutfehler gezeigt und einige
alte sowie innovative neue Techniken vorgestellt, wie mit Hilfe der
Open-Source-Bibliotheken http://fighting-layout-bugs.googlecode.com sowie
http://selenium.googlecode.com Layoutfehler automatisch erkannt werden können.

Weiterlesen