Seit einigen Monaten fragen sich Entwickler, was sie für ihre Akzeptanztests in neuen Projekten verwenden sollen. Nachdem CasperJS schon lange keine neue Version mehr veröffentlichte und Protractor nie wirklich für Angular-Projekte überzeugte, schien der Horizont in Bezug auf eine solide Lösung etwas verlassen. Aber es war nicht ohne auf die Gemeinschaft zu zählen, die geschaffen wurde Nachtwache (nein, es ist nicht dasselbe wie in Game of Thrones …)
Das Museum
Nightwatch ist ein Overlay zu Selen für Node.js, das es ermöglicht, letzteres dank des Protokolls zu kontrollieren Selenium JsonWireProtocol über eine einfache und elegante API.
Hier ist eine Illustration, die ziemlich gut darstellt, wie Nigtwatch mit Selenium und dann mit dem Browser funktioniert:

Nightwatch hebt sich in mehrfacher Hinsicht von der Konkurrenz ab:
- Wie bereits erwähnt, bleibt seine Syntax recht edel
- Es ist einfach zu erweitern (wir werden später in diesem Artikel sehen, wie)
- Integriert grundsätzlich das Muster von Seitenobjekt
- Mit Selen unter der Haube profitieren Sie vom Ökosystem dieser Plattform. Ich denke da insbesondere an Sass-Tools wie BrowserStack ou Sauce Labors und alle Fortsetzungen Webdriver die es Ihnen ermöglichen, sich mit allen Browsern zu verbinden.
- Aber das alles ist nichts im Vergleich zu dem, was für mich ein Killer-Feature ist: Nightwatch kann es Parallelisieren Sie die Ausführung Ihrer Testsuiten !
Zeig mir den Code!
Erste Schritte
Für die folgenden Erläuterungen beginnen wir mit der Baumstruktur der Nightwatch-Boilerplate-Projekt, das für den Artikel erstellt wurde, hier beschrieben:
├── Nachtwache.json
├── nightwatch.globals.js
├── jetzt
│ ├── Berichte
│ ├── Protokolle
│ └── Prüfungen
└── Paket.json
Wenn Sie die Lösung bereits vollständig haben möchten, rate ich Ihnen, dieses Repository direkt zu klonen.
Wie üblich beginnen wir mit der Installation von Paketen (im Stammverzeichnis des Projekts):
npm install nightwatch selenium-server-standalone-jar chromedriver --save-dev
Hier ist eigentlich nur die erste Abhängigkeit zwingend erforderlich, aber um Ihnen Zeit zu sparen, installieren wir zusätzlich ein Paket, das den Selenium-Server enthält (der in Form einer einfachen JAR-Datei vorliegt ), sowie ein weiteres, das den ChromeDriver enthält.
Der nächste Schritt ist das Erstellen der Nightwatch-Konfigurationsdatei mit dem Namen nightwatch.json . Hier ist die Beispieldatei, mit der wir arbeiten werden (ich werde die einzelnen Felder anschließend erläutern):
{
"src_folders" : ["nw/tests"],
"output_folder" : "nw/reports",
"globals_path" : "nightwatch.globals.js",
"test_workers": {
"enabled": true,
"workers": "auto"
},
"selenium" : {
"start_process" : true,
"server_path" : "./node_modules/selenium-server-standalone-jar/jar/selenium-server-standalone-2.50.1.jar",
"log_path" : "nw/logs",
"host" : "127.0.0.1",
"port" : 4444,
"cli_args" : {
"webdriver.chrome.driver" : "./node_modules/chromedriver/bin/chromedriver",
"webdriver.ie.driver" : ""
}
},
"test_settings" : {
"default" : {
"launch_url" : "http://google.com",
"selenium_port" : 4444,
"selenium_host" : "localhost",
"silent": true,
"screenshots" : {
"enabled" : true,
"path" : ""
},
"desiredCapabilities": {
"browserName": "chrome",
"javascriptEnabled": true,
"acceptSslCerts": true
}
},
"french" : {
"launch_url" : "http://google.fr",
"desiredCapabilities": {
"browserName": "firefox",
"javascriptEnabled": true,
"acceptSslCerts": true
}
}
}
}
- src_folders : Ordner, in denen Testsuiten zu finden sind.
- Ausgabeordner : Ordner zum Erstellen von Testberichten.
- test_worker : Ist der Teil, in dem wir definieren, ob unsere Testsuiten parallelisiert werden sollen. Hier definieren wir, dass sie „enabled:true“ sind und dass die Anzahl der Ausführungen der Anzahl der CPUs „workers:true“ entspricht.
- globals_path : Datei der globalen Parameter der Testsuiten, auf die wir etwas später zurückkommen werden.
- Selen : Dieser Teil definiert die allgemeine Konfiguration für die Verbindung zum Selenium-Server. Wir werden nicht darauf eingehen, aber beachten Sie, dass wir die Pfade für den Zugriff auf den Selenium-Server und den Chrome-Treiber angegeben haben.
- test_einstellungen : Dieser Teil ist wahrscheinlich der interessanteste, da er Ihnen erlaubt, Ihre Testumgebungen zu definieren. In diesem Beispiel definieren wir die Parameter der Standardumgebung und die der „französischen“ Umgebung. Beachten Sie, dass die zusätzlichen Umgebungen die Standardkonfiguration erben, weshalb wir nur die Ziel-URL unserer Umgebung („launch_url“) und den Browser mit („desiredCapabilities“) „überladen“ mussten.
Der `desiredCapabilities` -Block mag auf den ersten Blick etwas verwirrend wirken, wenn es nur um die Konfiguration des zu startenden Browsers geht. Tatsächlich stammt dieses Format direkt aus der Selenium-Konfiguration und ermöglicht die Einstellung zahlreicher Einstellungen im Zielbrowser. Weitere Informationen finden Sie in der offiziellen Dokumentation.
Erster Test
Es ist Zeit für unseren ersten Test; wir erstellen die Datei nw/tests/researchOnGoogle.test.js , die Folgendes enthält:
module.exports = {
'Search on google': (browser) => {
browser
.init()
.waitForElementVisible('body', 1000)
.setValue('input[type=text]', 'nightwatch')
.waitForElementVisible('button[name=btnG]', 1000)
.click('button[name=btnG]')
.pause(1000)
.assert.containsText('#main', 'Night Watch')
.end()
},
after: (browser) => {
browser.end()
}
};
Diese Datei beschreibt eine Testsuite, die unter anderem einen „Google-Suche“-Test enthält. Der Test beginnt mit einer ` init`-Anweisung , die die Seite lädt. Anschließend wartet er mit `waitForElement` , bis ein Element sichtbar wird , setzt mit `setValue` einen Wert im Suchfeld , klickt mit `click` auf die Suchschaltfläche (nachdem dessen Vorhandensein überprüft wurde) und pausiert eine Sekunde. Schließlich ruft die Funktion `after`, die von Nightwatch automatisch am Ende der Testsuite aufgerufen wird, die Methode ` end` auf.
Der Aufruf der `end` -Methode ist sehr wichtig, da sie den für den Test verwendeten Browser schließt. Daher empfehle ich Ihnen, sie am Ende jeder Testsequenz mit `after` aufzurufen.
Alles, was Sie tun müssen, ist es mit dem Befehl auszuführen node_modules/nightwatch/bin/nightwatch -c nightwatch.json

Wir haben ein Ergebnis ähnlich dem obigen Fenster sowie ein Chrome, das sich im Hintergrund öffnet, wo wir die angeforderten Manipulationen sehen. Möchten Sie jetzt die „französische“ Umgebung starten? Nichts leichter als das:
node_modules/nightwatch/bin/nightwatch -c nightwatch.json –env englisch
Kein Unterschied zur Konsole, andererseits ist es ein Firefox, der jetzt gestartet wird und der auf „http://google.fr“ statt auf „http://google.com“ der Standardumgebung geht.
Die „Globals“, um alles zu vereinfachen
Die globals-Datei ist sehr nützlich, um die Tests zu vereinfachen, indem globale Parameter definiert werden. Beispielsweise müssen wir derzeit systematisch die maximale Wartezeit definieren, um ein CSS-Element zu finden. Es wäre sehr praktisch, eine globale Wartezeit definieren zu können, das sind genau die Möglichkeiten, die diese Datei zusätzlich zur Definition bietet Haken zu verschiedenen Zeitpunkten während des Tests und um dynamische Umgebungsvariablen zu definieren (im Gegensatz zu den statischen Variablen in der „deklarativen“ JSON Nightwatch-Konfigurationsdatei).
Hier ist die Datei, die wir verwenden werden, die Kommentare helfen Ihnen, ihre Struktur zu verstehen:
module.exports = {
default: { // Paramètres de l'environement 'default'
searchTerm: 'nightwatch',
movieName: 'Night Watch'
},
french: { // Paramètres de l'environement 'french'
searchTerm: 'dikkenek',
movieName: 'dikkenek'
},
// Arrête tout dès qu'un test échoue
abortOnAssertionFailure: true,
// Délais entre deux vérifications
waitForConditionPollInterval: 300,
// Délais à attendre par défault
waitForConditionTimeout: 1000,
// Echoue si une selection retourne plusieurs éléments alors qu'elle devait n'en retourner qu'un
throwOnMultipleElementsReturned: false,
// Avant et après l'éxecution de l'ensemble des tests
before: (next) => next(),
after: (next) => next(),
// Avant et après chaque éxecution de suite des tests
beforeEach: (browser, next) => next(),
afterEach: (browser, next) => next(),
// Pour customiser le reporter de test
reporter: (results, next) => next()
};
Dadurch können wir die Testsuite wie folgt umgestalten:
module.exports = {
'Search on google': (browser) => {
browser
.init()
.waitForElementVisible('body')
.setValue('input[type=text]', browser.globals.searchTerm)
.waitForElementVisible('button[name=btnG]')
.click('button[name=btnG]')
.pause(1000)
.assert.containsText('#main', browser.globals.movieName)
.end()
},
after: (browser) => {
browser.end()
}
};
Sie werden die Verwendung dynamischer „globaler“ Variablen bemerken, die für jede Umgebung definiert sind. Sie sind sehr praktisch, wenn Sie beispielsweise vertrauliche Daten übergeben müssen, auf die nur als Umgebungsvariable zugegriffen werden kann.
Und gleichzeitig, was gibt es?
Da unsere Konfiguration die Test-Suites bereits parallel ausführt, müssen wir lediglich eine zweite Test-Suite hinzufügen, um sie gleichzeitig auszuführen. Erstellen wir also eine Suite namens nw/tests/nightWatchIsMovie.test.js wie folgt:
module.exports = {
'Go To google': (browser) => {
browser
.init()
.waitForElementVisible('body')
.setValue('input[type=text]', browser.globals.searchTerm)
.waitForElementVisible('button[name=btnG]')
.click('button[name=btnG]')
.pause(1000)
},
'Check movie name': (browser) => {
browser
.assert.containsText('.mod .kno-ecr-pt.kno-fb-ctx', browser.globals.movieName)
.assert.containsText('.mod ._gdf', '2004')
},
after: (browser) => {
browser.end();
}
};
Kleiner Unterschied zu dieser neuen Datei, wir haben mehrere Tests, aus denen unsere Suite besteht. Wir führen die Tests erneut durch und, TADA!

Sie haben zwei Testsuiten, die parallel in zwei verschiedenen Chroms laufen (vorausgesetzt, Sie haben mindestens zwei Kerne/CPU, was hoffentlich der Fall ist).
Überprüfung & Nachverfolgung
Mit einem nicht so unangenehmen Setup ist Nightwatch ein sehr einfach zu bedienendes Tool. Tatsächlich ist die minimale Konfiguration schnell zu implementieren, die Testsuiten bleiben lesbar und wartbar und die Suite-Parallelisierungsfunktion spart ungeheuer viel Zeit im Vergleich zur üblichen Zeit, um diese Art von Test durchzuführen!
Als Bonus sind die Testergebnisse dank der im Ordner vorhandenen xUnit-Ausgaben für den Entwickler im Terminal und für Ihr kontinuierliches Integrationssystem lesbar nw/berichte.
In einem zukünftigen Artikel werden wir uns mit Objektseiten und der Entwicklung komplexer Befehle und anderen Nightwatch-Tipps befassen.
Bleiben Sie dran ...
von Matthew Breton CTO bei JS-Republic.
