Grunt-lagen, Teil 2
Grunt kann außer der Codeanalyse auch Unittests automatisiert ausführen, beispielsweise in Zusammenarbeit mit Mocha. Besonders nützlich ist hierbei die kontinuierliche Ausführung von Grunt, die das Dateisystem im Hintergrund auf Änderungen überwacht und Grunt gegebenenfalls automatisch startet.
- Golo Roden
Nachdem Grunt vor einigen Wochen derart konfiguriert wurde, dass es auf Tastendruck eine Codeanalyse mit Hilfe von JSHint durchführt, wird es nun Zeit für den nächsten Schritt: Falls die Codeanalyse anstandslos durchlaufen wurde, wäre es zur weiteren Qualitätssicherung sinnvoll, auch die Tests auszuführen.
Voraussetzung hierfür ist natürlich, dass überhaupt Tests existieren. Wie diese implementiert werden, kann man beispielsweise im Artikel "Unit-Tests mit Node.js" nachlesen.
Mocha integrieren
Um Mocha im Rahmen von Grunt ausführen zu können, wird zunächst ein entsprechendes Modul benötigt. Ein solches steht mit grunt-mocha-test zur Verfügung, das man auf dem üblichen Weg in den lokalen Kontext der Anwendung installieren muss:
$ npm install grunt-mocha-test
Außerdem muss dieses Modul in der Datei Gruntfile.js als externe Aufgabe geladen und der default-Aufgabe als Abhängigkeit hinzugefügt werden:
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-mocha-test');
grunt.registerTask('default', [ 'jshint', 'mochaTest' ]);
Mocha konfigurieren
Als Nächstes ist Mocha innerhalb der Funktion grunt.initConfig zu konfigurieren. Dies erfolgt, anders als bei JSHint, über zwei separate Konfigurationsabschnitte:
- Der Abschnitt mochaTest definiert jene Dateien, welche die eigentlichen Tests enthalten und die dementsprechend von Mocha ausgeführt werden müssen.
- Die Konfiguration von Mocha selbst, also beispielsweise die Auswahl eines Reporters, wird hingegen im Abschnitt mochaTestConfig vorgenommen.
Eine einfache Konfiguration, die den TDD-Modus und den spec-Reporter von Mocha aktiviert und alle .js-Dateien aus dem test-Verzeichnis und dessen Unterverzeichnissen verwendet, sieht dann beispielsweise wie folgt aus:
grunt.initConfig({
jshint: { ... },
mochaTest: {
files: [ 'test/**/*.js' ]
},
mochaTestConfig: {
options: {
reporter: 'spec',
ui: 'tdd'
}
}
});
Die Optionen, die im Abschnitt mochaTestConfig angegeben werden, entsprechen jenen, die üblicherweise auch in der Datei test/mocha.opts hinterlegt sind. Derzeit ist das Modul grunt-mocha-test allerdings nicht in der Lage, die Optionen aus dieser Datei zu beziehen, weshalb die explizite Angabe in der Datei Gruntfile.js zwingend erforderlich ist.
Wird Grunt nun aufgerufen, werden zunächst alle .js-Dateien einschließlich der Testdateien einer Codeanalyse unterzogen. Falls diese anstandslos durchläuft, führt Grunt im Anschluss alle Tests aus.
Kontinuierliche Ausführung
Grunt führt die ihm übertragenen Aufgaben nun automatisiert aus – allerdings muss der Entwickler den Vorgang immer noch von Hand anstoßen. Wesentlich praktischer wäre es, wenn Grunt selbständig entscheiden könnte, wann ein erneuter Durchlauf erforderlich ist.
Diese Aufgabe übernimmt das Modul grunt-contrib-watch, das im Hintergrund ausgewählte Dateien kontinuierlich auf Änderungen überwacht und Grunt bei Bedarf erneut ausführt. Die Installation erfolgt ebenso wie die der anderen Module auf dem üblichen Weg in den lokalen Kontext der Anwendung:
$ npm install grunt-contrib-watch
Auch dieses Modul muss als externe Aufgabe in der Datei Gruntfile.js geladen werden, wird aber anders als die vorigen Module nicht der default-Aufgabe hinzugefügt:
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-mocha-test');
Stattdessen wird der Funktion grunt.initConfig lediglich ein weiterer Konfigurationsabschnitt hinzugefügt, der beschreibt, welche Dateien überwacht und welche Aufgabe im Falle des Falles auszuführen ist:
grunt.initConfig({
jshint: { ... },
mochaTest: { ... },
mochaTestConfig: { ... },
watch: {
options: {
files: [ '**/*.js', '!node_modules/**/*.js' ],
tasks: [ 'default' ],
interrupt: true
}
}
});
Die Option interrupt gibt darüber hinaus an, dass ein derzeit ausgeführter Durchlauf von Grunt abgebrochen werden darf, wenn ein neuer ausgeführt werden soll.
Um Grunt nun kontinuierlich auszuführen, muss man die watch-Aufgabe bei dessen Start explizit angeben:
$ grunt watch
Grunt startet und wartet zunächst darauf, dass Änderungen erkannt werden: Sobald eine neue Datei hinzugefügt oder eine bestehende geändert wird, führt Grunt wunschgemäß die default-Aufgabe aus.
Als ausgesprochen praktisch erweist sich in diesem Zusammenhang eine geteilte Ansicht, bei der man den Editor und die Konsole gleichzeitig im Blick hat. Auf diese Art ist bei jedem Speichern direkt ersichtlich, ob die Codeanalyse und die Tests des Projekts noch erfolgreich durchlaufen.
tl;dr: Grunt kann außer der Codeanalyse auch Unittests automatisiert ausführen, beispielsweise in Zusammenarbeit mit Mocha. Besonders nützlich hierbei ist die kontinuierliche Ausführung von Grunt, die das Dateisystem im Hintergrund auf Änderungen überwacht und Grunt gegebenenfalls automatisch startet. ()