Testautomatisierung für Webprojekte – Jenkins

In den vorangegangenen Artikeln wurden bereits Technologien zur Qualitätssicherung von Webanwendungen besprochen. Nun stellt sich die Frage wie diese automatisiert werden können. Außerdem muss es natürlich möglich sein Anpassungen vorzunehmen, die sich nach Projekt und speziellen Besonderheiten richten.

Tools

Im folgenden werden die Technologien besprochen welche dafür zur Anwendung kommen (können) und angerissen wie diese funktioniert.

Jenkins

Jenkins ist ein „Fork“ des schon lange bewährten Buildservers Hudson. Er wird verwendet, um automatisierbare Schritte der Qualitätssicherung auszuführen. Dazu gehört beispielsweise:

  • Überwachen der Versionsverwaltung (SVN, Git,..) auf neue „Commits“.
  • Ausführen Statischer Codeanalysen (JsLint für JavaScript zum Beispiel sehr gut um die Kompatibilität zum Internet Explorer zu verbessern).
  • Ausführen von phpUnit- / Seleniumtestsuiten.
  • Metriken erstellen

Selenium-Server

Selenium-Server ist ein kleines Java-Paket mit dem Selenium-Skripte remote ausgeführt werden können. Es wird benötigt wenn Selenium-Skripte nicht händisch per Selenium-IDE im Browser ausgeführt werden sollen, sondern wenn es darum geht diese per Kommandozeile, Buildserver usw. zu starten. Damit besteht auch die Möglichkeit den gleichen Test nicht nur in verschiedenen Browsern auszuführen sondern auch auf unterschiedlichen Maschinen (zum Beispiel eine Virtuelle Maschine mit Windows die auch auf einem Unix-Buildserver das Testen unter Microsoft Internet Explorer ermöglicht).

ANT-Buildskripte

ANT-Buildskripte sind grob beschrieben XML-Skripte die den Buildprozess abbilden. Dort wird festgelegt welche Schritte in Welcher Reihenfolge ausgeführt werden sollen. Weiterhin lassen sich sogenannte Buildtargets definieren, das heißt der Buildprozess kann auf verschiedenen Zielsystemen unterschiedlich aussehen. So lassen sich ANT-Buildskripte nicht nur von Jenkins ausführen sondern zum Beispiel auch innerhalb der Netbeans-IDE.

Statische Codeanalyse – Werkzeuge

Für die statische Codeanalyse existiert eine Vielzahl an Werkzeugen. Beispielhalft soll hier nur ein kleiner Teil beschrieben werden. Zur Qualitätssicherung von Webprojekten gehört auch die Kompatibilität zu verschiedenen Browsern. Diese kann nicht nur durch Akzeptanztests mit Selenium sichergestellt werden, sondern es gibt auch ein sehr nützliches Codeanalyse-Tool für JavaScript, dass viele „einfache Fehler“ erkennt. Gemeint ist das Projekt JsLint. Benutzt werden kann es händisch im Browser über die Projektwebseite, es integriert sich aber als Plugin auch in Netbeans oder kann mit einem JavaScript-Interpreter wie Rhino auch auf der Kommandozeile ausgeführt also von einem Buildserver verwendet werden. JsLint findet zum Beispiel „Trailing-Commas“, die bei den meisten Browsern problemlos verarbeitet werden aber im Internet Explorer zu erheblichen Problemen führen können.

PHPLoc bestimmt die Zeilenanzahl im PHPCode (LOC = Lines of Code)

CloverPHP berechnet die Codeabdeckung von PHPUnit-Tests

PHPDepend liefert Informationen über die Codestruktur wie zum Beispiel zirkuläre Abhängigkeiten

Die Liste lässt sich beliebig fortsetzen.

 

Integration / Umsetzung

Zunächst überlegt man sich einen sinnvollen Buildprozess. Der kann zwar später noch angepasst werden aber eine solide Basis spart Ärger und Zeit. Dazu gehört zum Beispiel dass man sich überlegt was getestet werden muss und wie kritisch die einzelnen Punkte sind. So ist es zum Beispiel durchaus möglich nach jedem Commit nur eine einfach statische Codeanalyse zu machen (und im Fehlerfall den Commit vie Pre-Commit-Hook zu verwerfen. Aber es sind auch „Nightly“-Builds denkbar die aufgrund ihrer Komplexität und Laufzeit nur einmal pro Nacht ausgeführt werden und die Entwickler per E-Mail über das Resultat informieren. Steht fest was wann in welchem Umfang zu testen ist kann begonnen werden mit der Implementierung der Buildskripte. An dieser Stelle wird vorraussgesetzt das die auszuführenden QA-Mechanismen wie Unittests, Seleniumtests usw. bereits existieren.

Es gibt ein „default“ Build-Target in Ant das man für den Jenkins-Buildserver verwenden sollte. Weitere Targets können definiert werden. So kann zum Beispiel ein Target für lokale Tests in Netbeans sinnvoll sein.

Ein grundlegendes Build-File kann zum Beispiel so aussehen (Dokumentation in Form von XML-Kommentaren):

<?xml version="1.0"?>
<project name="testprojekt" default="default">
  <!-- DEFAULT-Target für Jenkins -->
  <target name="default">
    <!-- PHPUnit ausführen -->
    <exec dir="${basedir}" executable="phpunit" failonerror="true">
      <arg line="--log-junit logfile.xml selenium/selenese_seleniumTests.php" />
    </exec>
  </target>
  <!-- Build-Target mit schärferen Tests für die Netbeans-IDE -->
  <target name="netbeans">
    <!-- Code-Dokumentation in HTML mit PHP-Doc erstellen -->
    <exec executable="phpdoc" dir="${basedir}">
      <arg line="-ct version,file
                 -ue on
                 -t /var/www/doku
                 -o HTML:Smarty:PHP
                 -d ../htdocs/app/cw
                 -dn caraworld
                 -s"/>
    </exec>
 
    <!-- Selenium-Tests mit PHP-Unit ausführen -->
    <exec dir="${basedir}" executable="phpunit" failonerror="true">
      <arg line="--log-junit logfile.xml selenium" />
    </exec>
 
    <!-- Statische Code-Analyse für JavaScript - jsLint -->
    <taskdef name="jslint"
           classname="com.googlecode.jslint4java.ant.JSLintTask"
           classpath="/opt/jslint4java/jslint4java.jar" />
    <jslint options="white,undef,plusplus,newcap,vars,indent=4,maxerr=50">
      <formatter type="plain" />
      <fileset dir="../htdocs/test/js" includes="*.js">
        <filename name="testfile.js" />
      </fileset>
    </jslint>
 
  </target>
</project>