Suche
Kolumne: Webentwicklung mit Angular

Isoliertes Karma: Angular Testing mit Docker

Karsten Sitterberg

(c) Shutterstock / Vilma20

Um Angular-Anwendungen zu testen, gibt es viele Möglichkeiten. Eine davon stellt Google mit dem Karma-Projekt zur Verfügung. Karsten Sitterberg stellt den Testrunner in dieser Kolumne vor und zeigt, wie Karma im Zusammenspiel mit Docker seine volle Mächtigkeit entfaltet.

Docker-Container erfreuen sich beim Bau von Anwendungen immer größerer Beliebtheit, da sich damit unterschiedliche Anwendungen und Umgebungen isoliert voneinander realisieren lassen. Gerade wenn es um Build, Testing und Deployment geht, lassen sich damit Seiteneffekte minimieren und reproduzierbare Ergebnisse sicherstellen. Bisher konnte Isolation lediglich durch vollständige Virtualisierungslösungen wie KVM, VirtualBox oder VMware realisiert werden. Damit geht jedoch ein deutlich größerer Ressourcenbedarf gegenüber Containern einher.

Docker & Karma

In diesem Beitrag betrachten wir, wie Entwickler von Angular-Anwendungen durch den Einsatz von Docker profitieren können. Typischerweise werden Angular-Anwendungen mit hoher Testabdeckung durch Unit-Tests entwickelt. Die Ausführung der in TypeScript oder ECMA-Script entwickelten Tests erfolgt mit einem Testrunner. Für Entwickler, die aus dem Java- oder .NET-Umfeld stammen, spielt der Testrunner eine ungewohnt bedeutende Rolle. Werden Unit Tests bei Java oder .NET durch dieselbe Laufzeitumgebung ausgeführt, die auch zum Entwicklungszeitpunkt bereitsteht, z.B. die Java JVM, so müssen hier die Tests durch eine JavaScript-Laufzeit ausgeführt werden.

Dazu kam früher z.B. die JavaScript-Engine von HtmlUnit zum Einsatz. Jeder Entwickler hat schon mindestens einmal im Leben die Situation erlebt, dass Abweichungen zwischen Entwicklungsumgebung und Produktionsumgebung zu schwer reproduzierbarem Verhalten geführt haben. So ist es auch bei HtmlUnit – die JavaScript Engine verhält sich anders als die Engines der durch die tatsächlichen Nutzer eingesetzten Browser. Manchmal kommt es zu Fehlern in HtmlUnit, während in einem echten Browser kein Problem besteht, aber auch umgekehrt.

Das Angular-Team hat sich daher entschlossen, eine Möglichkeit zu schaffen, die Tests mit der Engine eines echten Browsers auszuführen. Und zwar nicht nur mit der Engines eines Browsers, sondern mit den Engines eines beliebigen Browsers, denn auch unter diesen gibt es Abweichungen im Verhalten.

Das Ergebnis ist Karma, ein Testrunner, der stets einen Browser als Gastgeber verwendet.

Testen mit Karma – ein Beispiel

Auf einem typischen Entwicklersystem ist auch (mindestens ein) Browser installiert. Damit ist die Ausführung von Tests kein Problem. Ein einfaches Demoprojekt zur Ausführung von Karma-Tests lässt sich mit Angular CLI erzeugen:

ng new karma-demo

Die Tests können dann mittels ng test ausgeführt werden. Karma führt normalerweise alle Tests bei Änderungen erneut aus und beendet sich nicht nach einer einmaligen Testausführung. Möchte man lediglich einmal alle Tests laufen lassen, verwendet man ng test --watch false.
cd karma-demo
ng test --watch false

Karma unterstützt auch die Ausführung von Tests aus einer IDE heraus, wie hier am Beispiel von NetBeans zu sehen ist:

Auf einem Buildsystem ist im Gegensatz zu Entwickler-Rechnern jedoch meist keine volle grafische Oberfläche vorhanden, sodass kein Browser gestartet werden kann. Selbst wenn das System über eine grafische Oberfläche verfügt, möchte man nicht, dass parallel ausgeführte Tests sich gegenseitig beeinträchtigen. Dazu trägt Karma sein Möglichstes bei, indem es sich stets einer frischen Browserinstanz bedient. Es wird derzeit sogar daran gearbeitet, dass Karma Tests parallel ausführen kann. Dazu werden iFrames verwendet, die als Isolation dienen sollen.

Ein möglicher Weg, um auf einem nicht-grafischen System einen Browser zur Verfügung zu stellen, ist PhantomJS.

PhantomJS stellt einen headless Browser samt JavaScript API bereit und wird kontinuierlich weiterentwickelt. Damit hätte man im Prinzip alles, was zur Ausführung von Unit-Tests nötig ist. Eine beispielhafte Konfiguration fuer Karma könnte wie folgt aussehen:

// karma.conf.js
module.exports = function(config) {
 config.set({
   browsers: ['PhantomJS'],
   phantomjsLauncher: {
     exitOnResourceError: true
   }
 })
}

Auf der anderen Seite sind Tests mit den tatsächlich zum Einsatz kommenden Browsern unerlässlich, wie man an der Entwicklung von Karma selbst schon ablesen kann. Insofern ist eine Lösung gesucht, die es erlaubt, einen regulären Browser auf einem Buildserver ohne grafische Oberfläche zu starten und diesen Browser dann zur Ausführung von Karma-Tests zu verwenden.

Der übliche Weg führt dann zu einem X11-Server, der die grafische Oberfläche bereitstellt, jedoch lediglich “dunkel” arbeitet, also die Ausgabe in den Hauptspeicher statt auf eine Grafikkarte leitet. Dieser Framebuffer-X11-Server wird üblicherweise durch das Programm “xvfb” bereitgestellt. Die Verwendung mit Karma könnte dann folgendermaßen aussehen:


/usr/bin/Xvfb :10 &
export DISPLAY=:10.0

Enter Docker

Nicht auf allen Buildservern kann davon ausgegangen werden, dass das Paket installiert ist, und als Teil des Buildprozesses möchte niemand Änderungen an der Systemumgebung vornehmen. An dieser Stelle kommt nun Docker ins Spiel: Bietet der Buildserver Docker-Unterstützung, so kann darin der virtuelle X11-Server samt dem gewünschten Browser ausgeführt werden.

Für diesen Artikel wird der Docker Container trion/ng-cli-karma verwendet, welcher als Basis ein Image für Angular CLI nutzt. Hintergründe und Verwendungen sind hier beschrieben: Docker Build Container für Angular CLI.

Diesen Container führt man im oben erzeugten Projektverzeichnis aus:

docker run -u $(id -u) --rm -v "$PWD":/app trion/ng-cli-karma ng test

Die Ausgabe des Beispielprojekts sollte nun in etwa so aussehen:

Damit können Karma-Angular-Unit-Tests in einem Docker-Container ausgeführt werden. Die nächsten Schritte könnten sein, einen Buildserver wie beispielsweise Jenkins oder Gitlab CI für automatisierte Builds einzusetzen.

Lesen Sie auch:

Angular Tutorial: Rascher Projektstart mit dem Angular CLI

Geschrieben von
Karsten Sitterberg
Karsten Sitterberg
Karsten Sitterberg ist als freiberuflicher Entwickler, Trainer und Berater für Java und Webtechnologien tätig. Karsten ist Physiker (MSc) und Oracle-zertifizierter Java Developer. Seit 2012 arbeitet er mit trion zusammen.
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.