Automatisierte Bildschirmaufnahmen in CI/CD-Pipelines: Puppeteer und Playwright im Vergleich
Für Product Owner, Entwickler und weitere Stakeholder können Bildschirmaufnahmen hilfreich sein, um schnell und einfach einen Einblick in den Entwicklungsstand einer Webanwendung zu erlagen. In diesem Post berichte ich von meinen Erfahrungen, einen Prozess aufzusetzen, um in einer Build-Pipeline automatisch Videos und Screenshots einer Anwendung aufzunehmen und diese bereitzustellen. Realisiert habe ich dieses Vorhaben sowohl mit Playwright als auch mit Puppeteer.
Automatisierte Bildschirmaufnahmen
In einem aktuellen Projekt standen wir vor der Herausforderung, die Entwicklungsfortschritte unserer Webanwendung transparent und effizient in Form von Screenshots und Videos mit dem Kunden zu teilen.
Um dieses Ziel zu erreichen, bieten sich Tools für Ende-zu-Ende (E2E) Tests an, die nicht nur das Testen der gesamten Anwendung unter realistischen Bedingungen ermöglichen, sondern auch die automatische Aufnahme von Bildschirmaktivitäten unterstützen.
Bisher haben wir bei trion E2E-Tests hauptsächlich mit Cypress abgedeckt und dabei positive wie negative Erfahrungen gemacht. Da das konkrete Projekt mit Angular entwickelt wurde und für Angular kürzlich eine Vorlage für E2E-Tests mit Puppeteer erschienen ist, war das eine gute Gelegenheit, sich Puppeteer näher anzuschauen.
Zudem bot sich die Möglichkeit, Playwright als Alternative zu testen, womit ich zuvor noch nicht gearbeitet hatte.
Auch wenn ich beide Tools untersuche, soll dieser Post jedoch kein weiterer "Puppeteer vs. Playwright"-Vergleich sein. Davon gibt es bereits genügend. Vielmehr beschreibe ich, wie die beiden Tools in der Praxis eingesetzt werden können, um Entwicklungsprozesse zu vereinfachen und zu verbessern.
Puppeteer
Bereits 2019 haben wir uns angeschaut, wie man mit Puppeteer File-Downloads testen kann.
Wer Puppeteer mit Angular nutzen möchte, kann zum Einrichten eine Schematic verwenden:
ng add @puppeteer/ng-schematics
Anschließend lassen sich die Tests mit ng e2e
ausführen.
Ist man nicht mit Angular unterwegs, kann mit wenigen Befehlen eine ähnliche Umgebung inklusive TypeScript Support aufgebaut werden.
mkdir puppeteer && cd puppeteer
npm init
npm install --save-dev puppeteer jest ts-jest @types/jest typescript
npx ts-jest config:init
Ich habe mich für die Kombination mit dem Test Framework Jest entschieden, um später funktionale Tests ergänzen zu können.
Ein simpler Test sieht dann zum Beispiel so aus:
import { Browser, launch, Page } from 'puppeteer';
describe('trion website', () => {
let browser: Browser;
let page: Page;
beforeAll(async () => {
browser = await launch({headless: 'new'});
page = await browser.newPage();
});
afterAll(async () => {
await browser.close();
});
it('landing page', async () => {
const recorder = await page.screencast({
path: 'screencast.webm'
});
await page.goto('https://trion.de/');
await page.screenshot({path: 'screenshot.png'});
await new Promise((res) => setTimeout(res, 750));
await recorder.stop();
});
});
Anschließend das ganze mit npx jest
ausführen.
Puppeteer zeichnet den Besuch der trion Webseite als Bild (page.screenshot()
) und Video (page.screencast()
) auf.
Damit das Screen Recording klappt, muss jedoch das Tool ffmpeg installiert sein.
Wer Docker installiert hat, kann alternativ das Ganze auch in einem passenden Container ausführen. Das Image trion/ng-cli-e2e kommt mit allen benötigten Tools, um Puppeteer laufen zu lassen.
docker run --rm \
-v "$(pwd):/app" \
-w /app \
-e PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome \
trion/ng-cli-e2e \
/bin/bash -c "npm ci && npx jest" # Alternativ: ng e2e
Die Umgebungsvariable PUPPETEER_EXECUTABLE_PATH
zeigt Puppeteer einen geeigneten Browser zum Ausführen des Tests.
Mit dieser Vorbereitung kann das Setup auch leicht in eine Build-Pipeline integriert werden.
steps: - name: puppeteer image: trion/ng-cli-e2e environment: - PUPPETEER_EXECUTABLE_PATH: /usr/bin/google-chrome script: - npm ci - npx jest volume: - ... # Volume für Videos und Screenshots
Anschließend können die Aufzeichnungen auf einer beliebigen Platform veröffentlicht werden.
Playwright
Playwright ist ein Open-Source-Tool, das 2020 von Microsoft veröffentlicht wurde. Es wurde speziell für die Durchführung von End-to-End-Tests moderner Webanwendungen entwickelt.
Mit folgendem Befehl kann Playwright zu einem Projekt hinzugefügt werden:
npm init playwright
Der Puppeteer-Test von oben würde mit Playwright dann so aussehen:
import { test } from '@playwright/test';
test('landing page', async ({ page }) => {
await page.goto('https://www.trion.de/');
await page.screenshot({ path: 'screenshot.png' });
await new Promise((res) => setTimeout(res, 750));
});
Die API von Playwright ähnelt der von Puppeteer an vielen Stellen sehr. Ein wesentlicher Unterschied besteht jedoch darin, dass Playwright seinen eigenen Test-Runner mitliefert, den wir anstelle von Jest nutzen.
Mittels npx playwright test
wird der Test ausgeführt.
In der Standardkonfiguration sogar jeweils für Chromium, Firefox und WebKit.
Um Videos von einem Testlauf (hier für Chromium) zu erstellen, wird die playwright.config.ts
wie folgt angepasst:
export default defineConfig({
// ...
projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
video: {
mode: 'on'
}
}
},
// ...
],
// ...
})
Das Video findet man anschließend im Ordner test-results
; Screenshots unter dem im Code angegebenen Pfad.
Playwright stellt ein eigenes Docker Image bereit, mit dem die Tests ausgeführt werden können:
docker run --rm --ipc=host \
-v "$(pwd):/app" \
-w /app \
mcr.microsoft.com/playwright \
/bin/bash -c "npm ci && npx playwright test"
Ähnlich wie Puppeteer lässt sich auch Playwright in einer Build-Pipeline starten. Die offizielle Dokumentation gibt dafür einige Beispiele.
Recording von Testabläufen
Bei der Betrachtung von Puppeteer und Playwright war es mir wichtig, Interaktionen auf der Webseite einfach aufzeichnen zu können.
Dies war insbesondere deshalb relevant, da für eine zentrale Komponente des Projekts noch eine grundlegende Änderung geplant war. Eine solche Änderung erfordert normalerweise umfangreiche Anpassungen im Testcode, was sowohl zeit- als auch ressourcenintensiv sein kann.
Durch das Aufzeichnen von Benutzerinteraktionen lässt sich der benötigte Testcode schnell und kostengünstig erstellen. Obwohl dieser Code in Sachen Wartbarkeit oder Lesbarkeit häufig keine Auszeichnung gewinnt, stellt er eine effektive und kostengünstige Lösung für eine Übergangsphase dar, um flexibel auf Änderungen reagieren zu können.
Playwrights Test Generator
Ein Tool zum Generieren von Test-Code wird bei Playwright direkt mitgeliefert. Der Test-Generator wird wie folgt aufgerufen:
npx playwright codegen myurl
Mit nur wenigen Klicks kann man die Interaktionen mit der Anwendung in Playwright-Befehle verwandeln.
Für das Durchklicken der trion Webseite schlug der Test Generator beispielsweise folgenden Code vor:
import { test } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('https://www.trion.de/');
await page.getByRole('navigation').getByRole('link', { name: 'Entwicklung' }).click();
await page.getByRole('navigation').getByRole('link', { name: 'Beratung' }).click();
await page.getByRole('navigation').getByRole('link', { name: 'Schulung' }).click();
await page.getByRole('link', { name: 'SQL Grundlagen (ISO/IEC 9075)' }).click();
await page.getByRole('link', { name: ' Schulung buchen' }).click();
});
Ein solides Ergebnis mit übersichtlichen Selektoren für die Elemente, mit denen interagiert wird.
Puppeteer Code mit Chrome DevTools aufzeichnen
Auch Puppeteer erlaubt es, Interaktionen aufzuzeichnen.
Statt eines speziellen Tools nutzt man hierfür allerdings den Recorder der Google Chrome DevTools. Dieser kann die aufgezeichneten Aktionen direkt als Puppeteer-Code exportieren. Über Erweiterungen werden übrigens auch Playwright und Cypress unterstützt.
Hier bekommt man ein Standalone Skript geliefert, dass sich zwar direkt per node.js ausführen lässt, sich jedoch nur mit einigen Anpassungen in den typischen Aufbau eines Testcases integrieren lässt:
(async () => {
// ...
{
const promises = [];
const startWaitingForEvents = () => {
promises.push(targetPage.waitForNavigation());
}
startWaitingForEvents();
await targetPage.goto('https://www.trion.de/');
await Promise.all(promises);
}
{
const promises = [];
await puppeteer.Locator.race([
targetPage.locator('ul.show-for-medium > li.entwicklung > a')
])
.setTimeout(timeout)
.click({
offset: {
x: 76,
y: 18,
},
});
await Promise.all(promises);
}
await browser.close();
})().catch(err => {
console.error(err);
process.exit(1);
});
Was mir am Recorder gut gefallen hat: Vor Beginn der Aufzeichnung kann man einstellen, welche Selektoren das Tool erfassen soll.
Zudem kann angegeben werden, ob spezielle Test-Attribute wie z.B. data-test
vorhanden sind.
Im Code werden dann mehrere Möglichkeiten zum Selektieren eines Elements asynchron ausprobiert.
Das Vorgehen ist im Vergleich zu Playwright weniger komfortabel und erfordert mehr Nachbereitung. Insgesamt ist das Ergebnis jedoch für eine temporäre Lösung in Ordnung.
Fazit
Sowohl mit Playwright als auch mit Puppeteer lassen sich einfach Videos und Screenshots von Webanwendungen aufnehmen. Die Integration in eine CI-Pipeline ist, zumindest für solche eher einfachen Fälle, schnell erledigt.
Auch bei der Qualität der Videos und Screenshots konnte ich keine großen Unterschiede ausmachen.
Mir persönlich hat jedoch Playwright in der Handhabung besser gefallen. Durch den mitgelieferten Testrunner und Codegenerator bietet der Microsoft-Kandidat eine reibungslose Integration und einen schnellen Einstieg. Gerade für größere Projekte bietet Playwright durch die Unterstützung verschiedener Browser und die gute Integration in CI-Pipelines eine hohe Flexibilität und Effizienz bei der Testautomatisierung. Dass Puppeteer im Vergleich zu Playwright im Bereich der E2E-Testfunktionen etwas dünner aufgestellt ist, verwundert nicht, da Puppeteer primär als API zur Steuerung von Chromium konzipiert wurde.
Für unsere Zwecke waren insgesamt jedoch beide Tools bestens geeignet.
Beispielcode für Puppeteer und Playwright ist bei GitHub zu finden: https://github.com/trion-development/screen-capture-puppeteer-playwright
Zu den Themen Docker, Webentwicklung und Angular bieten wir sowohl Beratung, Entwicklungsunterstützung als auch passende Schulungen an:
Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.