Playwright-Fixtures & Parametrisierung

Dieses Kapitel führt in den Fixture-Mechanismus von Playwright ein, in die Erstellung benutzerdefinierter Fixtures und in Techniken für parametrisierte Tests.


Was ist ein Fixture

Ein Fixture ist ein Dependency-Injection-Mechanismus für Parameter von Playwright-Testfunktionen.

Jeder Test erhält die benötigten Fixtures durch Destrukturieren von Parametern (z. B.,{ page }), und Playwright übernimmt Erstellung und Bereinigung.

Beispiel

// page und context sind integrierte Fixtures
test('Verwendung integrierter Fixtures', async ({ page, context }) => {
  // Playwright erstellt automatisch page und context
  // Wird nach dem Testende automatisch bereinigt
  await page.goto('https://www.example.com/');
});

Kurzreferenz für integrierte Fixtures

FixtureTypeBeschreibung
pagePageUnabhängiger Browser-Tab
contextBrowserContextBrowserkontext
browserBrowserBrowser-Instanz
browserNamestringAktueller Browsername
requestAPIRequestContextHTTP-Anfrageclient

Benutzerdefinierte Fixtures

Übertest.extend()Benutzerdefinierte Fixtures erstellen, um zusätzliche Abhängigkeiten einzufügen oder integrierte Fixtures zu überschreiben.

Beispiel

// Dateipfad: tests/fixtures.ts
import { test as base, expect } from '@playwright/test';

// Typ der benutzerdefinierten Fixture definieren
type MyFixtures = {
  todoPage: { goto: () => Promise<void>; addTodo: (text: string) => Promise<void> };
  authenticatedPage: any;
};

export const test = base.extend<MyFixtures>({
  // Benutzerdefinierte Fixture: Todo-Seitenobjekt
  todoPage: async ({ page }, use) => {
    // Erstellen
    const todoPage = {
      goto: async () => {
        await page.goto('https://demo.playwright.dev/todomvc');
      },
      addTodo: async (text: string) => {
        await page.getByPlaceholder('Was muss erledigt werden?').fill(text);
        await page.keyboard.press('Enter');
      },
    };
    // In den Test injizieren
    await use(todoPage);
    // Aufräumlogik (falls nötig)
  },

  // Benutzerdefinierte Fixture: Authentifizierte Seite
  authenticatedPage: async ({ browser }, use) => {
    const context = await browser.newContext({
      storageState: 'playwright/.auth/user.json',
    });
    const page = await context.newPage();
    await use(page);
    await context.close();
  },
});

export { expect };

Benutzerdefinierte Fixtures verwenden

Beispiel

// Dateipfad: tests/todo.spec.ts
import { test, expect } from './fixtures';

test('Todo hinzufügen', async ({ todoPage }) => {
  await todoPage.goto();
  await todoPage.addTodo('Playwright lernen');
  await todoPage.addTodo('Fixtures meistern');
  // Überprüfen...
});

Fixture-Bereiche

Fixtures haben drei Bereiche, gesteuert durch diescopeOption.

GeltungsbereichWertLebenszyklus
Test-Ebene (Standard)scope: 'test'Einmal pro Test erstellt
Worker-Ebenescope: 'worker'Einmal pro Worker-Prozess erstellt, von allen Tests im selben Worker gemeinsam genutzt

Beispiel

// Fixture auf Worker-Ebene (von allen Tests im selben Worker gemeinsam genutzt)
const test = base.extend({
  sharedResource: [async ({}, use) => {
    const resource = await createExpensiveResource();
    await use(resource);
    await resource.dispose();
  }, { scope: 'worker' }],  // Beachte die Array-Syntax
});

Fixtures auf Worker-Ebene werden über mehrere Tests innerhalb desselben Worker-Prozesses hinweg geteilt; geeignet für Ressourcen mit hohem Erstellungsaufwand wie Datenbankverbindungen.


Überschreiben integrierter Fixtures

Du kannst integrierte Fixtures überschreiben, um das Standardverhalten zu ändern.

Beispiel

const test = base.extend({
  // Überschreibe die integrierte page-Fixture, um den Standard-Viewport zu ändern
  page: async ({ baseURL, page }, use) => {
    await page.setViewportSize({ width: 1920, height: 1080 });
    await use(page);
  },

  // storageState überschreiben
  storageState: 'playwright/.auth/admin.json',
});

Automatische Fixture-Bereinigung

Die Bereinigungslogik der Fixture wird nach demuse()Aufruf ausgeführt, ähnlich der Wirkung vonafterEach.

Beispiel

const test = base.extend({
  tempUser: async ({ request }, use) => {
    // Temporären Benutzer erstellen
    const resp = await request.post('/api/users', {
      data: { name: 'temp_' + Date.now() },
    });
    const user = await resp.json();

    // In den Test injizieren
    await use(user);

    // Automatische Bereinigung: Temporären Benutzer löschen
    await request.delete(`/api/users/${user.id}`);
  },
});

Parametrisierte Tests

Playwright verfügt über keinen integrierten Parametrisierungsmechanismus, aber Tests können mithilfe von Schleifen dynamisch generiert werden.

Beispiel

// Datengetriebener Test
const testCases = [
  { username: 'admin', password: 'admin123', expected: 'Dashboard' },
  { username: 'user',  password: 'user123',  expected: 'Persönlicher Bereich' },
  { username: 'guest', password: 'guest123', expected: 'Besucherseite' },
];

for (const { username, password, expected } of testCases) {
  test(`Benutzer ${username}sieht $ nach der Anmeldung{expected}`, async ({ page }) => {
    await page.goto('/login');
    await page.getByLabel('Username').fill(username);
    await page.getByLabel('Password').fill(password);
    await page.getByRole('button', { name: 'Login' }).click();
    await expect(page.getByText(expected)).toBeVisible();
  });
}

Test-Annotationen

Annotationen werden verwendet, um Metadaten zu Tests hinzuzufügen, die im Reporter angezeigt und gefiltert werden können.

Beispiel

test('Test mit Annotation', async ({ page }) => {
  // Annotation hinzufügen (innerhalb des Testfunktionskörpers)
  test.info().annotations.push({
    type: 'issue',
    description: 'https://github.com/example/bug/123',
  });
  test.info().annotations.push({
    type: 'description',
    description: 'Dieser Test deckt alle Verzweigungen des Login-Flows ab',
  });

  // Testlogik...
});

// Tag verwenden (im Testnamen)
test('Schneller Smoke-Test @smoke @critical', async ({ page }) => {
  // Sie können nur diesen Test mit npx playwright test --grep "@smoke" ausführen
});
Andere Erweiterungen