Robot Framework Fachtests in Eclipse entwickeln und mit Maven ausführen

2 Kommentare

Das Robot Framework ist sehr flexibel einsetzbar und hat uns noch nie vor unlösbare Probleme gestellt. An manchen Enden jedoch muss noch etwas nachgebessert werden, um die Entwicklung und Wartung der automatisierten Tests effizienter gestalten zu können. Einer dieser Bereiche ist die Einbettung in die gewohnte Entwicklungsumgebung. Es gibt zwar die Robot IDE, diese deckt aber nur einen Bruchteil des Benötigten ab. Hier wird gezeigt, wie man das Robot Framework und selbstentwickelte Java Keywords bequem mit Eclipse und Maven nutzen kann.


Robot wird über ein Startskript gestartet, je nach Umgebung jybot.sh oder jybot.bat. (Wenn man auf Java Keywords verzichtet, reicht auch ein pybot). Über eine Vielzahl an Parametern wird gesteuert, welche Tests ausgeführt werden sollen. Vorher sollten auch noch die eigenen Keywords kompiliert und in den Classpath eingebunden werden. Da die Entwicklung häufig in Windows stattfindet, die CI-Umgebung aber unter Linux läuft, sind somit zwei nicht-triviale Skripte zu pflegen, um die Robot Tests aufzurufen. Das geht auch einfacher:

1. Maven

Statt das Startskript manuell zu pflegen, kann jybot direkt aus Maven gestartet werden. Die Beispiel pom.xml weiter unten zeigt die Details:

  • Mit dem maven-dependency-plugin werden alle libraries in ein Verzeichnis kopiert, welches nachher in den Classpath eingebunden wird. So können auch Bibliotheken von Drittanbietern bequem genutzt werden.
  • Das exec-maven-plugin ruft in dem Phase integration-test ‚jybot‘ auf. Dies erfordert natürlich, dass jybot auch im PATH der jeweiligen Umgebung eingebunden ist. Auf ein explizites .sh oder .bat kann hier zum Glück verzichtet werden.
  • Der Classpath wird auf

    ${project.build.directory}${file.separator}classes${path.separator}
    ${project.build.directory}${file.separator}dependency${file.separator}*

    gesetzt. Das heißt er beinhaltet

    1. Die kompilierten Klassen der eigenen Java Keywords
    2. Alle jar-Dateien der in der pom.xml angegebenen dependencies. (Die Wildcard-Notation funktioniert nur mit Java 6!)
  • Dann wird das jybot-Skript entsprechend parametrisiert:
    • -C off stellt die farbige Ausgabe ab
    • –variable … übergibt einige Variablen. Diese werden im properties-Element der pom.xml auf entwicklerfreundliche Defaultwerte gesetzt. Ist die Umgebungsvariable „env“ auf „ci“ gesetzt, d.h. läuft der Maven Build im Kontext des CI-Servers, wird das entsprechende Profil aktiviert, welches die Variablen auf die für das Testsystem relevanten Werte setzt.
    • –variable RESOURCES:${project.basedir}/src/main/robot/resource Dadurch können Resources in den Testfällen einfach mit ${RESOURCES}/keyword-file.txt referenziert werden.
    • –exclude inprogress Dies schließt alle Testfälle aus, die momentan in Bearbeitung sind. Dadurch kann ein Entwickler Zwischenstände commiten, ohne dass der CI-Server diese Tests schon ausführt. Sobald ein Test funktioniert, muss das Tag natürlich entfernt werden.
    • –include author-* Alle Tests sollten meiner Meinung nach mit einem author versehen werden. Dieses include schließt somit alle tests ein, bietet aber dem Entwickler die Möglichkeit die Tests auf wenige einzuschränken, an denen er aktuell arbeitet. Dies ließe sich auch durch Maven Properties und Profiles weiter vereinfachen. Es gibt momentan noch einen Bug in Jython, der jeden Parameter versucht zu passenden Dateinamen zu expandieren (Jython Issue 1567) – es sollte also keine Datei geben, die auf author-* matched.
    • ${ROBOT_TESTS} Dies gibt letztlich an, welche Tests ausgeführt werden sollen. Normalerweise sind das alle Tests in ${project.basedir}/src/main/robot/suite. Durch die Möglichkeit des Tagging und der Verzeichnishierarchie hat man somit zwei unanbhängige Möglichkeiten die Testfälle zu verwalten und zur Ausführung auszuwählen. Das sollte ausreichend Flexibilität bieten.

Langfristig wäre es natürlich schöner, gleich ein Plugin für maven zu schreiben, statt umständlich das Skript zu parametrisieren. Bis es soweit ist, sollte die hier vorgestellte Lösung aber hinreichend sein.

<project>
...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.1</version>
        <executions>
          <execution>
            <id>get dependencies</id>
            <phase>pre-integration-test</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.1.1</version>
        <executions>
          <execution>
            <id>robot</id>
            <phase>integration-test</phase>
            <goals>
              <goal>exec</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <executable>jybot</executable>
          <environmentVariables>
            <CLASSPATH>${project.build.directory}${file.separator}classes${path.separator}${project.build.directory}${file.separator}dependency${file.separator}*</CLASSPATH>
          </environmentVariables>
          <arguments>
            <argument>-C</argument>
            <argument>off</argument>
            <argument>--variable</argument>
            <argument>SYSTEM_UNDER_TEST:${system-under-test}</argument>
            <argument>--variable</argument>
            <argument>DB_PORT:${db.port}</argument>
            <argument>--variable</argument>
            <argument>RESOURCES:${project.basedir}/src/main/robot/resource</argument>
            <argument>--outputdir</argument>
            <argument>${project.build.directory}/robot</argument>
            <argument>--output</argument>
            <argument>${project.groupId}-${project.artifactId}-${project.version}-output.xml</argument>
            <argument>--log</argument>
            <argument>${project.groupId}-${project.artifactId}-${project.version}-log.html</argument>
            <argument>--report</argument>
            <argument>${project.groupId}-${project.artifactId}-${project.version}-report.html</argument>
            <argument>--exclude</argument>
            <argument>inprogress</argument>
            <argument>--include</argument>
            <argument>author-*</argument>
            <argument>${ROBOT_TESTS}</argument>
          </arguments>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <profiles>
    <profile>
      <id>ci-common</id>
      <activation>
        <property>
          <name>env</name>
          <value>ci</value>
        </property>
      </activation>
      <properties>
        <db.port>1234</db.port>
        <system-under-test>testservername</system-under-test>
      </properties>
      </build>
    </profile>
  </profiles>
  <properties>
    <ROBOT_TESTS>${project.basedir}/src/main/robot/suite</ROBOT_TESTS>
    <db.port>4711</db.port>
    <system-under-test>localhost</system-under-test>
  </properties>
</project>

2. Struktur des Projektes

Mit der oben angegebenen pom.xml ergibt sich in Eclipse die folgende Projektstruktur – entweder durch das m2eclipse-Plugin oder durch die Verwendung des eclipse:eclipse Goals des maven-eclipse-Plugins.

3. Robot Starten

Die Ausführung der automatisierten Fachtests ist dann nur noch eine Frage des Aufrufs des entsprechenden Maven-Lebenszyklus:

4. Selenium Server

Werden mit Robot auch Browser-Tests durchgeführt, bietet es sich an, den Seleniumserver als „External Tool“ in Eclipse zu integrieren:

5. Kompletter Workflow

Anhand des konkreten Beispiels soll in einem kleinen Screencast vermittelt werden, wie in Eclipse die Testfälle entwickelt und gestartet werden. Da man die Details bei dem eingebettetem Video schlecht erkennen kann, habe ich auch eine Fullscreen-Version bereitgestellt.

Andreas Ebbert-Karroum

Andreas Ebbert-Karroum ist Agile Principal Consultant bei codecentric und Product Owner von CenterDevice.

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentare

  • Mika

    You can probably omit Step 4 totally if you use RF SeleniumLibrary to start and stop the selenium server ?

  • Andreas Ebbert-Karroum

    Mika,

    good point. In our CI environment the selenium server is running on a different machine, than the build server, so there this would not work. For the developer, it should be possible to start the selenium server from withtin the robot framework. I think it should be even possible to share the settings for the selenium server that way. I will give that a thought 🙂

    Andreas

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.