Puppenspieler mit ES6 in einem Knoten und Browser oder warum Zora das beste Testframework in seiner Nische ist

Alles ist in Ordnung, solange Sie die JS-Quellen durch die Dummies laufen lassen müssen, um ein Bundle zu erstellen, aber die Hölle beginnt, wenn Sie Tests für Ihre Site oder Bibliothek schreiben möchten. Das Problem ist, dass alle Test-Frameworks bestimmte Funktionen von einem Knoten verwenden und / oder in ES5 geschrieben sind. Das Starten von E2E-Tests ist daher keine triviale Aufgabe mehr und bietet das Tanzen mit einem Tamburin aus Transpilationen und Quellenkarten, um den Code abzudecken. Sie möchten nicht, dass die Fehler auf die falsche Stelle verweisen?



In diesem Artikel werde ich meine Erfahrungen mit Puppenspieler für eine kleine Aufgabe beschreiben.
und wie ich ES6-Module im Knoten und Browser gestartet habe, die nur eine Quelle für Tests ohne Kollektoren haben.


Warum überhaupt Puppenspieler, fragen Sie, warum nicht WebDriver? Ich habe gerade bemerkt, wie die Schöpfer der beliebten Open-Source-WebGL-Bibliotheken gequält werden. Sie haben beispielsweise 300 Seiten mit Beispielen, von denen jede mit jedem Commit brechen kann. Sie überprüfen sie nach jeder Änderung, und wenn sie vergessen haben, etwas zu öffnen - sorry ¯\_(ツ)_/¯ , es ist kaputt ¯\_(ツ)_/¯ . Wenn noch niemand dieses Problem gelöst hat, habe ich beschlossen, es in meiner kleinen Bibliothek zu versuchen. Der erste Gedanke war, kopflos zu laufen, aber es ist veraltet. Node-gles unterstützt bereits WebGL2, aber nicht die seltene Erweiterung, die ich verwendet habe. WebDriver? Ich habe es noch nicht einmal versucht. Ich bin mir nicht sicher, ob dies möglich ist. Ich brauchte kein Python / C # / Java, aber ich brauchte JS / TS mit dem neuesten Knoten und der neuesten Browser-API, damit die Flugfunktionen den neuesten Spezifikationen entsprechen können.


Warum sind ES6-Module? Die Unterstützung für WebGL und ES6 in Browsern ist ungefähr gleich. Und mit Bundle-Modulen oder nicht, lassen Sie den Benutzer entscheiden, Sie können einfach beide Versionen sammeln. Es stellt sich jedoch heraus, dass es für Unit-Tests sehr praktisch ist, die Version mit den Modulen zu verwenden, da Sourcemaps sehr einfach extrahiert werden und Sie die Tests anschließend ohne zusätzliche Gesten im Knoten oder im Browser ausführen können. Wenn Sie sie als Puppenspieler ausführen, ist E2E mit Codeabdeckung fast kostenlos. Typoskript mit einem Ziel in ES6 wurde wahrscheinlich benötigt, aber bei einem kleinen Projekt, das mit Tests abgedeckt ist, funktioniert auch normales js.


Also, genug Einführungen, habe ich puppeteer und puppeteer-to-istanbul in das Projekt aufgenommen und einen solchen Wrapper geschrieben


 // puppeteer.js import puppeteer from 'puppeteer'; import pup2ist from 'puppeteer-to-istanbul'; (async () => { const browser = await puppeteer.launch({ headless: process.env.HEADLESS, // headless customization slowMo: 250 // good fature for new configs }); const page = (await browser.pages())[0]; // enable coverage await page.coverage.startJSCoverage(); await page.coverage.startCSSCoverage(); // some additional code with console events here... // navigate to unit test page await page.goto('http://127.0.0.1:1234/'); // disable coverage const jsCoverage = await page.coverage.stopJSCoverage(); const cssCoverage = await page.coverage.stopCSSCoverage(); pup2ist.write([...jsCoverage, ...cssCoverage]) await new Promise(resolve => setTimeout(resolve, 6000)); await browser.close(); })(); 

node --experimental-modules --no-warnings ./test/puppeteer.js kann mit dem Befehlsknoten node --experimental-modules --no-warnings ./test/puppeteer.js mit einem Knoten ab 11 oder sogar ohne Flags auf Knoten 13.2+ ausgeführt werden. Natürlich können Sie require , dann ... Aber warum? Dies ist in der Regel ein Backend, hier wird nicht einmal Kundenbetreuung benötigt! Mit dem folgenden Code aus package.json können wir HEADLESS-Downloads in der Konsole und in der CI-Cloud anpassen, wenn für sie unterschiedliche Einstellungen erforderlich sind. In travs / circle-ci wird wahrscheinlich Linux installiert, und Sie können dort Umgebungsvariablen in diesem Format festlegen. öffnet concurrently zwei Prozesse in einer Konsole parallel.


 // package.json { //bla-bla... "type": "module", // this line indicates that we are using es6 modules "scripts": { "test": "node --experimental-modules --no-warnings ./test/puppeteer.js", "server": "http-server -c-1 -p 1234", "not-bad-cmd--dude": "concurrently -k -s first \"npm:test\" \"npm:server\"", "ci": "HEADLESS=true concurrently -k -s first \"npm:test\" \"npm:server\"", } } 

Auf dem lokalen Computer wird nach Eingabe des Befehls npm run server der http- npm run server gestartet und auf dem npm run test Testpuppenspieler in einem separaten Fenster, dem Chrome-Fenster. Das ist im Grunde alles, was Sie über Puppenspieler wissen müssen. Weitere Beispiele zu Screenshots, Geräteemulationen, Administrationsbereichen usw. finden Sie hier . Übrigens haben Sie zusammen mit dem puppeteer Paket ein separates Chrom in node_modules installiert. Wenn Sie es nicht benötigen, ersetzen Sie es durch puppeteer-core oder puppeteer-firefox . Es sollte beachtet werden, dass wir im obigen Beispiel eine kostenlose JS / CSS-Codeabdeckung erhalten haben, die im Ordner .nyc_output geschrieben ist. Bis wir uns darauf konzentrieren, ist es zu diesem Zeitpunkt nicht kalt, es ist nicht heiß, aber wenn es etwas gibt, ist es da und Statistiken Die Testabdeckung kann fast angezeigt werden.



Kommen wir nun zu den Tests selbst und versuchen zu entscheiden, wo ich E2E in meiner kleinen Bibliothek ausführen soll. Ich bin auf die folgenden Grafiken gestoßen, in denen die Leistung von Frameworks zum Testen verglichen wurde. Wahrscheinlich ist die Laufzeit nicht so wichtig, aber wenn einige Jest sie zehnmal langsamer starten, stellt sich die Frage, was es ist und warum es benötigt wird. Das Hauptauswahlkriterium war es6 mit der Zeile <script type="module" src="./test.js"></script> auf der HTML-Seite. Da der Knoten zum Zeitpunkt des Schreibens meines Codes ES6 noch nicht vollständig unterstützte (gestern wurde 12.3 veröffentlicht, wodurch die Flags entfernt wurden). Ich entschied, dass, wenn Sie das Framework mit den Quellen auf TS oder ES6 + nehmen, es definitiv beginnen sollte. Im Allgemeinen könnten Sie wahrscheinlich eine Art Mokka nehmen, ihn auf der Seite höher deklarieren und auf die deklarierte Klasse verweisen. Was passiert jedoch, wenn ein Fehler auftritt? Im Allgemeinen können Sie hier Ihren bevorzugten Läufertest benennen. Ich möchte nur sagen, dass Zora das TAP-Format unterstützt, und das bedeutet, dass ein ganzer Zoo von TAP-Essern dafür geeignet ist. Es hat die meisten Behauptungen, es unterstützt Async, es ist eines der schnellsten, geschrieben in reinem ES6 ohne Abhängigkeiten vom Knoten selbst. Es schien mir ein echter Diamant für kleine Projekte.


Als Ergebnis habe ich einige Tests erhalten, die sowohl im Browser als auch im Knoten funktionieren. Die Zora- Dokumentation enthält umfassende Anweisungen zu Zusicherungen und Gruppierungen von Befehlen.


 // test.js import MyLibrary from '../dist/my-library.module.js'; import { test } from 'https://cdn.jsdelivr.net/npm/zora@3.0.3/dist/bundle/module.js'; test('CPU', async (t) => { // some stuff here t.ok(tfps != null, 'fps = ' + (tfps != null ? tfps.toFixed(1) : 'null')); t.ok(tcpu != null, 'cpu = ' + (tcpu != null ? tcpu.toFixed(1) : 'null')); }); test('Memory', async (t) => { // some stuff here t.ok(tmem != null, 'mem = ' + (tmem != null ? tmem.toFixed(1) : 'null')); }); // etc... 

Um die Konsole ohne Baugruppen zu zeigen, musste ich einen ähnlichen Schnüffler machen. Die nackte Konsole ist nicht sehr präsentabel, es wäre möglich, den TAP-Ausgang irgendwo anzuschließen, um den Marathon zu leiten. Aber das Lustige ist, dass die Testergebnisse Ihres Kunden online angezeigt werden können. Außerdem wird bei jedem Commit genau der gleiche Code in CI ausgeführt.


 <!DOCTYPE html> <html lang="en"> <head> <!-- some declarations in head --> </head> <body> <!-- some declarations in body --> <script> const addSniffer = (spyTarget) => function() { spyTarget.apply(window.console, arguments); sniffer([...arguments]); } window.console.log = addSniffer(window.console.log); window.console.error = addSniffer(window.console.error); let screen = document.getElementById('screen'); function sniffer(string) { let screen = document.getElementById("screen"); string.forEach(line => { let div = document.createElement("div"); let text = document.createTextNode(line); div.appendChild(text) screen.appendChild(div); }); } </script> <script type="module" src="./test.js"></script> </body> </html> 

Aber das ist noch nicht alles. Mit vorgefertigten Tests können Sie Bots wie renovate / greenkeeper / Dependabot verbinden, die Abhängigkeiten in Ihrer Bibliothek aktualisieren und automatische Commits durchführen, nachdem Sie die Richtigkeit der Aktualisierungen überprüft haben. Und travis / github-ci / circle-ci hätte eine neue Version von npm-Paketen hochgeladen.


Beispielsweise führt eine solche Konfiguration aus "Renovieren" an Sonntagen automatische Festschreibungen durch und erhöht die Version


 { "automerge": true, "automergeType": "branch", "bumpVersion": "patch", "schedule": ["on sunday"], "ignorePaths": [".circleci"] } 

Und Travis kann das Paket automatisch auf npm hochladen, wenn Sie selbst die Version oder einen Bot erstellt haben. Erstellen Sie dazu ein Konto auf travis-ci.org , aktivieren Sie f2a wie in diesem Artikel beschrieben , geben Sie zwei geheime Schlüssel $NPM_EMAIL und $NPM_TOKEN und erstellen Sie eine ähnliche Konfiguration.


 language: node_js node_js: '12' script: - npm run ci deploy: provider: npm edge: true email: $NPM_EMAIL api_key: $NPM_TOKEN on: branch: master 

Insgesamt ist es irgendwie möglich, aber es ist schwierig, Benachrichtigungen vom Github zu entfernen, dass eine Sicherheitsanfälligkeit in einer Art Abhängigkeit aufgetreten ist: D.

Source: https://habr.com/ru/post/de466551/


All Articles