Astro-Entwickler in Essen

Wie ich eine Astro-Website vor jedem Deploy prüfe: Unit-Tests mit Vitest, Komponenten mit der Container API, Ende-zu-Ende-Tests mit Playwright gegen den Preview-Build, Link- und Barrierefreiheitsprüfung. Für Betriebe in Essen und NRW.

Astro-Entwickler

Migration von WordPress zu Astro in Essen

Viele Unternehmen in Essen nutzen WordPress, stoßen aber an Grenzen bei Performance, Sicherheit und Hosting-Kosten. Astro löst diese Probleme mit statischem HTML, null JavaScript und Edge-Deployment. Ich migriere bestehende WordPress-Seiten zu Astro mit vollständiger SEO-Erhaltung, URL-Mapping und 301-Weiterleitungen.

  • PageSpeed 95-100

    Statisches HTML ohne JavaScript. Schneller als jede WordPress-Lösung.

  • SEO-sichere Migration

    URL-Mapping, 301-Weiterleitungen, Google-Rankings erhalten.

  • Hosting auf Cloudflare Pages

    Globales CDN, kostenloses SSL, sofortige Deployments. Hosting-Kosten nahe null.

Eine Astro-Seite geht selten kaputt, weil Astro versagt. Sie geht kaputt, weil jemand eine Komponente ändert und eine Seite vergisst, die sie auch nutzt. Tests holen diese Fälle vor den Deploy. Hier steht, welche vier Schichten ich bei Astro einsetze, was jede erkennt und wie sie in einer Pipeline zusammenlaufen. Versionen im Text: Stand November 2026, laut npm-Registry Astro 7.4.11, Vitest 5.1.0, Playwright 1.65.0 und @axe-core/playwright 4.14.0.

#Welche Tests braucht eine Astro-Website?

SchichtWerkzeugLäuft gegenErkennt
Typenastro checkQuellcodeTypfehler auch in .astro-Dateien
EinheitenVitestFunktionen und HilfsmoduleFehler in Formatierung, Sortierung, URL-Bau
KomponentenContainer APIEinzelne .astro-KomponenteFalsches HTML bei bestimmten Props und Slots
GesamtseitePlaywrightPreview des BuildsKaputte Links, Formulare, Navigation, axe-Verstöße

Die Astro-Dokumentation behandelt Vitest und die Container API unter Unit- und Integrationstests und Playwright unter Ende-zu-Ende-Tests (Testing). astro check prüft laut CLI-Referenz auch in .astro-Dateien auf Typen und beendet sich bei Fehlern mit Exit-Code 1. Die Dokumentation nennt den Befehl ausdrücklich für CI. Wie ich TypeScript in Astro-Projekten sonst einsetze, steht in meiner Bielefelder Seite.

Efeubewachsenes Haus in der Essener Margarethenhöhe

Foto: Basotxerri, CC BY-SA 4.0, Wikimedia Commons.

#Wie richte ich Vitest in einem Astro-Projekt ein?

Vitest braucht laut vitest.dev Vite ab 6.4.0 und Node ab 22.12.0. Testdateien müssen standardmäßig .test. oder .spec. im Namen tragen, und vitest run führt die Tests einmal aus, ohne Dateien zu beobachten. Für Astro kommt die Konfiguration aus getViteConfig, damit Vitest dieselbe Vite-Konfiguration sieht wie der Build:

/// <reference types="vitest/config" />
import { getViteConfig } from 'astro/config';

export default getViteConfig({
  test: {
    // Vitest-Optionen
  },
});

getViteConfig() lädt laut Dokumentation standardmäßig die Astro-Konfiguration des Projekts. Seit Astro 4.8 lässt sich ein zweites Argument übergeben, etwa site oder trailingSlash, wenn Tests eine andere Astro-Konfiguration brauchen.

Was gehört in Vitest? Reine Funktionen: ein Hilfsmodul, das aus einem Titel einen Slug baut, eine Sortierung von Einträgen, ein Formatierer für Datumsangaben. Ein Beispiel für Inhaltsmodelle mit Zod-Schema finden Sie bei den Content Collections in Stuttgart; dort ist das Schema der Test, der beim Build abbricht, und Vitest prüft nur die Logik darum herum.

#Wie teste ich Astro-Komponenten mit der Container API?

Die Container API rendert eine .astro-Komponente zu einem String, ohne Browser und ohne Server. Sie kam mit Astro 4.9.0. Die Referenz nennt sie experimentell und warnt vor Änderungen auch in Minor- und Patch-Releases. Das ist der wichtigste Grund, die Astro-Version zu fixieren.

import { experimental_AstroContainer as AstroContainer } from 'astro/container';
import { expect, test } from 'vitest';
import Card from '../src/components/Card.astro';

test('Card zeigt den Titel', async () => {
  const container = await AstroContainer.create();
  const html = await container.renderToString(Card, {
    props: { title: 'Wartung' },
    slots: { default: 'Text im Slot' },
  });
  expect(html).toContain('Wartung');
  expect(html).toContain('Text im Slot');
});

Die Optionen von renderToString laut Referenz:

  • props und slots füllen die Komponente. Der Standard-Slot heißt default.
  • request brauchen Komponenten, die Astro.url oder Astro.request lesen.
  • params setzt Astro.params für dynamische Routen, locals setzt Astro.locals.
  • partial ist standardmäßig true: Die Komponente erscheint ohne Seitengerüst. Mit false enthält die Ausgabe auch <!DOCTYPE html>, was bei Layouts nötig ist.

Enthält eine Komponente React, Vue oder MDX, braucht der Container Renderer. In Vitest holen Sie sie mit getContainerRenderer aus dem Entrypoint container-renderer der jeweiligen Integration und loadRenderers aus dem virtuellen Modul astro:container. Die Referenz listet React, Preact, Solid, Svelte, Vue und MDX auf. Welche UI-Frameworks sich in Astro sinnvoll mischen lassen, behandelt die Seite für Dresden, den Umgang mit Markdown und MDX die Seite für Bonn.

Die Grenze: Der Container liefert HTML. Ob eine Insel im Browser hydriert, sehen Sie dort nicht. Das gehört in Playwright, wie bei den Islands in Wiesbaden beschrieben.

#Wie laufen Ende-zu-Ende-Tests gegen den Preview-Build?

Die Astro-Dokumentation rät, Tests gegen den Produktionscode laufen zu lassen. Der Ablauf: erst npm run build, dann npm run test:e2e. Playwright startet dabei den Preview-Server selbst. astro preview dient laut CLI-Referenz nur der lokalen Prüfung des dist-Ordners und ist nicht für den Produktivbetrieb gedacht. Für Tests genügt es.

import { defineConfig } from '@playwright/test';

export default defineConfig({
  webServer: {
    command: 'npm run preview',
    url: 'http://localhost:4321/',
    timeout: 120 * 1000,
    reuseExistingServer: !process.env.CI,
  },
  use: {
    baseURL: 'http://localhost:4321/',
  },
});

Aus der Playwright-Dokumentation zu webServer: Playwright wartet, bis die url mit einem Statuscode wie 2xx oder 3xx antwortet. Die Option port gilt als veraltet, timeout steht standardmäßig auf 60000 Millisekunden. Mit reuseExistingServer: !process.env.CI nutzt ein lokaler Lauf einen bereits laufenden Server, die CI startet immer neu. Wegen baseURL genügen in den Tests relative Pfade wie page.goto('/kontakt/').

Welche Seiten ich teste: je Seitentyp eine, nicht jede. Startseite, eine Leistungsseite, ein Beitrag, Kontakt, Impressum. Pro Seite prüfe ich Statuscode, die eine h1 und das Vorhandensein von Navigation und Fußzeile. Bei mehrsprachigen Auftritten läuft dieselbe Prüfung je Sprache, siehe die Seite für Zürich. Wer Seitenübergänge einsetzt, prüft die Navigation per Klick statt per direktem Aufruf, weil beide Wege unterschiedlich laufen können.

Formulare brauchen einen eigenen Test. Mit page.route fange ich die Anfrage des Formulars ab, damit der Test keine echte Mail auslöst und keine echten Daten verschickt. Das passt zur Datenschutzseite: Die Landesbeauftragte für Datenschutz und Informationsfreiheit Nordrhein-Westfalen bietet Muster für Datenschutzhinweise für einfache Websites an, und Testdaten sollten nie echte Kundendaten sein. Zu Formularen und Actions in Astro lesen Sie mehr auf der Seite für Wuppertal.

Astro bringt keinen Linkprüfer mit. Die Testing-Seite nennt dafür nichts. Ich löse es mit dem Request-Fixture von Playwright, das laut API-Testing-Dokumentation baseURL berücksichtigt. Der Test sammelt die internen Links einer Seite und ruft jeden ab:

import { expect, test } from '@playwright/test';

test('interne Links der Startseite antworten', async ({ page, request }) => {
  await page.goto('/');
  const hrefs = await page
    .locator('a[href^="/"]')
    .evaluateAll((as) => [...new Set(as.map((a) => a.getAttribute('href')))]);
  for (const href of hrefs) {
    const res = await request.get(href!);
    expect(res.ok(), href!).toBeTruthy();
  }
});

Das prüft interne Links gegen den Build, nicht externe Ziele. Externe Links ändern sich ohne Ihr Zutun und gehören nicht in eine Pipeline, die einen Deploy blockieren soll. Dafür genügt eine getrennte, gelegentliche Prüfung. Einen vollständigen Linkplan für einen Umzug von einem alten System finden Sie im Testplan vor dem Go-live. Dort stehen Weiterleitungen, Metadaten und der Bildschirmvergleich, die ich hier nicht wiederhole.

#Wie prüfe ich Barrierefreiheit automatisch?

Das Paket @axe-core/playwright führt die axe-Engine in einem Playwright-Test aus (Accessibility testing):

import AxeBuilder from '@axe-core/playwright';
import { expect, test } from '@playwright/test';

test('Startseite ohne erkennbare axe-Verstöße', async ({ page }) => {
  await page.goto('/');
  const results = await new AxeBuilder({ page })
    .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
    .analyze();
  expect(results.violations).toEqual([]);
});

Die Dokumentation sagt zwei Dinge, die ich bei jedem Projekt weitergebe. Erstens erkennen automatisierte Tests nur einige häufige Probleme, andere lassen sich nur manuell finden. Zweitens schließt exclude() ein Element samt allen Nachkommen von allen Regeln aus, nicht nur von der einen, die Sie stört. Wer damit einen Fehler stummschaltet, verliert die Prüfung für den ganzen Bereich.

Zum Hintergrund: Das Barrierefreiheitsstärkungsgesetz gilt nach § 1 Abs. 3 Nr. 5 BFSG für Dienstleistungen im elektronischen Geschäftsverkehr, die für Verbraucher nach dem 28. Juni 2025 erbracht werden. Nach § 3 Abs. 3 BFSG gilt § 3 Abs. 1 nicht für Kleinstunternehmen, die Dienstleistungen anbieten. Ob Ihr Betrieb darunter fällt, entscheide nicht ich, sondern eine fachkundige Stelle. Der axe-Test ist ein technischer Baustein, kein Konformitätsnachweis.

#Wie läuft die Pipeline vor jedem Deploy?

Die Playwright-Dokumentation zu CI zeigt einen GitHub-Actions-Workflow mit npm ci, npx playwright install --with-deps, npx playwright test und dem Hochladen des Ordners playwright-report. Ich ergänze Typprüfung, Vitest und Build und lasse den Deploy erst danach zu:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: lts/*
      - run: npm ci
      - run: npx astro check
      - run: npx vitest run
      - run: npm run build
      - run: npx playwright install --with-deps
      - run: npx playwright test
      - uses: actions/upload-artifact@v5
        if: ${{ !cancelled() }}
        with:
          name: playwright-report
          path: playwright-report/
  deploy:
    needs: test
    runs-on: ubuntu-latest
    # Deploy-Schritte des jeweiligen Hosters

needs: test bewirkt, dass ein roter Test den Deploy verhindert. Die Reihenfolge geht vom Billigen zum Teuren: Typen, Unit-Tests, Build, Browser. Wo die fertigen Dateien danach liegen, hängt vom Hosting ab, siehe die Seite zu Hosting-Adaptern in Berlin.

Zwei Fallen aus der Playwright-Dokumentation. Bildschirmfotos mit toHaveScreenshot hängen von Betriebssystem, Browser und Hardware ab, die Referenzbilder müssen in derselben Umgebung entstehen, in der sie später verglichen werden. Ich erzeuge sie deshalb in der CI und nicht auf dem Laptop. Und die Dokumentation empfiehlt reuseExistingServer: !process.env.CI, damit auf der CI nie versehentlich ein alter Server antwortet.

#Wann setze ich welche Schicht ein?

Ihre SeiteMindestumfang
Wenige Seiten, ein Formularastro check, Build, Playwright für Kontaktformular und Statuscodes
Bibliothek eigener Komponentenzusätzlich Container-Tests für Komponenten mit Varianten
Viele Inhalte aus Collectionszusätzlich Vitest für die Hilfsfunktionen, Linkprüfung je Seitentyp
Mehrere Sprachendieselben Playwright-Tests je Sprache
Pflicht zur Barrierefreiheitaxe-Test je Seitentyp, dazu manuelle Prüfung

#So läuft ein Testprojekt mit mir

Ich bin ein einzelner Entwickler und arbeite remote und schriftlich, ohne Termine oder Telefonate. Der Ablauf:

  1. Sie schicken mir das Repository, die Adresse der Seite und die Liste der Formulare.
  2. Ich lese den Code und schreibe auf, welche Seitentypen und Komponenten Tests bekommen und welche nicht.
  3. Sie bestätigen den Umfang schriftlich. Was darüber hinausgeht, wird gesondert eingeschätzt.
  4. Ich baue Tests und Pipeline auf einem Branch. Sie prüfen den Lauf im Pull Request.
  5. Nach der Abnahme läuft die Pipeline bei jedem Push. Auf Wunsch betreue ich sie weiter, Stunden aus einem Paket verfallen am Monatsende.

Layout und Texte bleiben Ihre Sache. Ich teste, was die Seite ausliefert.

#Häufige Fragen

#Muss ich eine kleine Unternehmensseite überhaupt testen?

Ein Minimum lohnt sich immer: ein Build, der bei Fehlern abbricht, ein Test pro Seitentyp, der Startseite, Kontaktseite und Impressum auf Statuscode und Überschrift prüft, und ein Test des Kontaktformulars. Mehr braucht eine Seite mit zehn Unterseiten selten. Der Umfang wächst mit der Zahl der Komponenten und der Zahl der Personen, die am Code arbeiten.

#Ist die Container API stabil genug für ein Kundenprojekt?

Die Astro-Dokumentation nennt sie experimentell und schließt Änderungen auch in Minor- und Patch-Releases nicht aus. Ich fixiere deshalb die Astro-Version, lese bei jedem Update das Changelog und halte die Container-Tests klein. Fällt die Schnittstelle weg, ersetzen Playwright-Tests auf den gebauten Seiten das Wesentliche.

#Warum Playwright gegen astro preview und nicht gegen den Entwicklungsserver?

Weil die Astro-Dokumentation rät, Tests gegen den Produktionscode laufen zu lassen. Der Entwicklungsserver verarbeitet Dateien anders als der Build, etwa bei Bildern, Skripten und eingebundenen Styles. Ein Test, der dort grün ist, sagt wenig über das, was später ausgeliefert wird.

#Ersetzt die axe-Prüfung eine Barrierefreiheitsprüfung nach BFSG?

Nein. Die Playwright-Dokumentation sagt selbst, dass automatisierte Tests nur einen Teil der Probleme erkennen und andere nur manuell auffallen. axe verhindert, dass bekannte Fehler wie fehlende Beschriftungen unbemerkt zurückkehren. Tastaturbedienung, sinnvolle Alternativtexte und Lesereihenfolge prüfe ich zusätzlich von Hand.

#Läuft die Pipeline auch bei meinem Hoster?

Die Tests laufen in der CI, nicht beim Hoster. Sie brauchen ein Repository mit einer Pipeline, etwa GitHub Actions oder GitLab CI, und Node ab der Version, die Vitest verlangt. Wo die fertigen Dateien danach liegen, ist für die Tests unerheblich.

#Was brauche ich von Ihnen, damit ich Tests bekomme?

Zugriff auf das Repository, die Adresse der Seite, eine Liste der Formulare und Seitentypen und die Angabe, wo heute deployt wird. Layout und Texte bleiben bei Ihnen, ich teste, was vorhanden ist. Für den Umfang bekommen Sie vorab eine schriftliche Einschätzung ohne Berechnung.

#Schreiben Sie mir vor dem nächsten Deploy

Schicken Sie mir über das Kontaktformular die Adresse Ihrer Website, das Repository, die Liste der Formulare und den Hoster, bei dem heute deployt wird. Mein Antwortweg ist die Mail, an Werktagen. Die Einschätzung zum Testumfang bekommen Sie kostenlos und schriftlich.

Brauchen Sie die Leistung: Astro-Entwickler in Essen?

Beschreiben Sie Ihr Projekt per E-Mail. Antwort innerhalb von 48 Stunden.

Projekt beschreiben

Weitere WordPress-Dienste und Wissensbasis entdecken