Playwright Locators

Ein Locator ist eines der Kernkonzepte in Playwright. Er stellt eine Möglichkeit dar, Elemente auf einer Seite zu finden.

Dieses Kapitel stellt die von Playwright empfohlenen Lokalisierungsmethoden vor: Lokalisierung von Elementen nach Rolle, Text, Label und Platzhalter.


Was ist ein Locator

Ein Locator ist ein abstraktes Objekt, das Playwright verwendet, um Elemente auf einer Seite zu finden.

Im Gegensatz zu traditionellendocument.querySelector()In vielerlei Hinsicht hat der Locator von Playwrightautomatisches Warten und automatisches WiederholenFähigkeiten.

Wenn sich der Seiteninhalt dynamisch ändert, sucht der Locator kontinuierlich nach Elementen, bis er ein passendes Element findet oder ein Timeout auftritt.

Beispiel

// Erstelle einen Locator (keine Elementsuche findet sofort statt)
const button = page.getByRole('button', { name: 'Submit' });

// Wenn eine Aktion ausgeführt wird, wartet Playwright automatisch darauf, dass die Schaltfläche erscheint und interagierbar wird.
await button.click();

Wie Locators funktionieren

Wenn du einen Locator erstellst, zeichnet Playwright nur eine Suchregel auf.

Wenn Sie.click()、.fill()Aktionen oderexpect(locator)Assertions aufrufen, beginnt der Locator tatsächlich, Elemente zu finden.

Wenn das Element nicht gefunden werden kann, wird der Locator weiterhin versuchen, bis für den Vorgang ein Timeout eintritt.


Lokalisieren nach Rolle: getByRole()

getByRole()ist die von Playwright am meisten empfohlene Lokalisierungsmethode.

Es verwendet dieBarrierefreiheitsrolle (ARIA Role)des Elements, um Elemente zu finden, was der Art und Weise, wie Benutzer sie wahrnehmen, am nächsten kommt.

Grundlegende Verwendung

Beispiel

// Einen Button anhand der Rolle "button" lokalisieren
const submitBtn = page.getByRole('button', { name: 'Submit' });
await submitBtn.click();

// Einen Link anhand der Rolle "link" lokalisieren
const homeLink = page.getByRole('link', { name: 'Startseite' });
await homeLink.click();

// Eine Überschrift anhand der Rolle "heading" suchen
const mainTitle = page.getByRole('heading', { name: 'Willkommen bei EXAMPLE' });

// Ein Textfeld anhand der Rolle "textbox" suchen
const searchBox = page.getByRole('textbox', { name: 'Suche' });
await searchBox.fill('Playwright');

Häufige ARIA-Rollen

RolleEntsprechende HTML-ElementeAnwendungsbeispiel
'button'<button>、role="button"getByRole('button', { name: '登录' })
'link'<a>getByRole('link', { name: '了解更多' })
'heading'<h1>~<h6>getByRole('heading', { name: 'EXAMPLE 教程' })
'textbox'<input type="text">、<textarea>getByRole('textbox', { name: '用户名' })
'checkbox'<input type="checkbox">getByRole('checkbox', { name: '记住我' })
'radio'<input type="radio">getByRole('radio', { name: '男' })
'combobox'<select>getByRole('combobox', { name: '城市' })
'img'<img>getByRole('img', { name: 'Logo' })
'list'<ul>、<ol>getByRole('list')
'listitem'<li>getByRole('listitem')
'navigation'<nav>getByRole('navigation')
'table'<table>getByRole('table')

Die Option „name“

nameDie Option verwendet denzugänglichen Namendes Elements, um den Bereich einzugrenzen.

Zu den Quellen des zugänglichen Namens gehören: der Textinhalt des Elements,aria-labelAttribute, zugehörig<label>usw.

Beispiel

// Nach Button-Text abgleichen
page.getByRole('button', { name: 'Login' });

// Nach aria-label abgleichen
page.getByRole('button', { name: 'Close dialog' });

// Abgleich mit regulärem Ausdruck
page.getByRole('link', { name: /EXAMPLE|rookie/ });

Zustandsoptionen

Zusätzlich zuname,getByRoleunterstützt es außerdem mehrere Zustandsoptionen:

Beispiel

// Die aktivierte Checkbox lokalisieren
page.getByRole('checkbox', { checked: true });

// Den deaktivierten Button lokalisieren
page.getByRole('button', { disabled: true });

// Das erweiterte Dropdown-Menü lokalisieren
page.getByRole('button', { expanded: true });

// Die ausgewählte Option lokalisieren
page.getByRole('option', { selected: true });

// Mehrere Zustände kombinieren
page.getByRole('checkbox', { name: 'Agree to the terms', checked: false });

Lokalisierung nach Text: getByText()

getByText()Anhand desTextinhaltsdes Elements lokalisieren.

Beispiel

// Exakte Textübereinstimmung
page.getByText('Welcome to EXAMPLE');

// Teilweise Übereinstimmung (Standard)
page.getByText('EXAMPLE');

// Exakte Übereinstimmung erzwingen
page.getByText('EXAMPLE', { exact: true });

// Übereinstimmung mit regulärem Ausdruck
page.getByText(/EXAMPLE|rookie tutorial/);

getByTextEs stimmt mit dem vollständigen Textinhalt des Elements überein, dahergetByText('EXAMPLE', { exact: true })stimmt es nur mit Elementen überein, deren Textinhalt genau "EXAMPLE" ist.

Standardmäßig, wenn keine exakte Übereinstimmung verwendet wird, ist eine Teilstring-Übereinstimmung ausreichend (zum Beispiel,getByText('EXAMPLE')wird es mit "Welcome to EXAMPLE" übereinstimmen).


Auffinden anhand von Label: getByLabel()

getByLabel()Wird verwendet zum Auffinden<label>zugehöriger Formularelemente.

Beispiel

// HTML-Struktur:
// <label for="username">Username</label>
// <input id="username" type="text" />

// Das Eingabefeld über den Labeltext lokalisieren
await page.getByLabel('Username').fill('example_user');

// HTML-Struktur:
// <label>Password <input type="password" /></label>

// Verschachtelte Labels sind ebenfalls gültig
await page.getByLabel('Password').fill('password123');

Es unterstützt außerdem{ exact: true }Optionen für exakte Übereinstimmung.


Auffinden anhand des Platzhalters: getByPlaceholder()

getByPlaceholder()Durch dieplaceholderplaceholder-Attribut, um Eingabefelder zu lokalisieren.

Beispiel

// HTML-Struktur: <input placeholder="Please enter a search keyword" />
await page.getByPlaceholder('Please enter a search keyword').fill('Playwright');

// HTML-Struktur: <textarea placeholder="Tell us what you think..."></textarea>
await page.getByPlaceholder('Tell us what you think...').fill('The EXAMPLE tutorial is great!');

Auswahl zwischen getByLabel und getByPlaceholder

MethodeAnwendungsszenarioPriorität
getByLabel()Wenn ein <label>-Element vorhanden istZuerst verwenden
getByPlaceholder()Wenn kein Label vorhanden ist, aber ein Placeholder existiertZweite Wahl

getByRoleist die von Playwright am meisten empfohlene Lokalisierungsmethode, da sie simuliert, wie Benutzer Elemente anhand ihrer Rolle identifizieren. Als Nächstes folgengetByLabelundgetByPlaceholder. Ziehen Sie es nur in Betracht, wenn keine semantischen Elemente vorhanden sind.getByTestIdoder CSS-Selektoren.


getByAltText() zur Bildlokalisierung

getByAltText()Durch dasaltalt-Attribut des Bildes zum Auffinden<img>des <img>-Elements.

Beispiel

// HTML:<img src="logo.png" alt="EXAMPLE Logo" />
await expect(page.getByAltText('EXAMPLE Logo')).toBeVisible();

// Übereinstimmung mit regulärem Ausdruck
await expect(page.getByAltText(/logo/i)).toBeVisible();

getByTitle() zum Auffinden über das title-Attribut

getByTitle()Durch dastitletitle-Attribut des Elements zum Auffinden.

Beispiel

// HTML: <button title="Close current page">X</button>
await page.getByTitle('Close current page').click();

getByAltTextundgetByTitleWird seltener verwendet; nur wenn das Element ein explizites alt- oder title-Attribut hat und nicht auf andere Weise lokalisiert werden kann.


getByTestId

getByTestId()JaFallback-Lösung, überdata-testidAttribut, um das Element zu lokalisieren.

Beispiel

// HTML: <button data-testid="submit-btn">Submit</button>
await page.getByTestId('submit-btn').click();

// Kann mehrere Übereinstimmungen enthalten (z. B. Listenelemente)
const items = page.getByTestId('todo-item');
await expect(items).toHaveCount(3);

Anpassen des testId-Attributs

Wenn Ihr Projekt nicht verwendetdata-testid, können Sieplaywright.config.tsPassen Sie den Attributnamen an in:

Beispiel

// Dateipfad: playwright.config.ts
export default defineConfig({
  Verwenden Sie: {
    // data-cy statt data-testid verwenden (für Cypress-Migration)
    testIdAttribute: 'data-cy',
    // Oder id als testId verwenden
    // testIdAttribute: 'id',
  },
});

page.locator() CSS- und XPath-Lokalisierung

page.locator()Unterstützt CSS-Selektoren und XPath und dient als flexiblerer Fallback.

CSS-Selektoren

Beispiel

// Nach CSS-Klassennamen
await page.locator('.submit-btn').click();

// Nach ID
await page.locator('#username').fill('example_user');

// Nach Attribut
await page.locator('[data-type="primary"]').click();

// Nach Tag- + Klassen-Kombination
await page.locator('button.primary').click();

// Nach Eltern-Kind-Beziehung
await page.locator('nav a').first().click();

// CSS-Selektor, der bestimmten Text enthält
await page.locator('button:has-text("Submit")').click();

XPath-Lokalisierung

Beispiel

// Mit XPath lokalisieren
await page.locator('xpath=//button[@type="submit"]').click();

// Nach Text lokalisieren
await page.locator('xpath=//h1[contains(text(), "EXAMPLE")]').click();

CSS-Selektoren und XPath sind das letzte Mittel; priorisiere die Verwendung vongetByRole、getByTextSemantische Lokalisierungsmethoden. CSS-Selektoren neigen dazu, durch Style-Refactoring zu brechen, und XPath ist schlecht lesbar und langsamer.


Locator-Verkettung

Der Locator von Playwright unterstützt Verkettung, wodurch die aktuellen Treffer weiter gefiltert werden können.

.first()、.last()、.nth()

Beispiel

// Erstes passendes Listenelement abrufen
const firstItem = page.getByRole('listitem').first();

// Letztes abrufen
const lastItem = page.getByRole('listitem').last();

// Das zweite abrufen (Index beginnt bei 0)
const secondItem = page.getByRole('listitem').nth(1);

.filter() Filterung

Beispiel

// Buttons mit bestimmtem Text filtern
page.getByRole('button').filter({ hasText: 'Save' });

// Diejenigen herausfiltern, die keinen bestimmten Text enthalten
page.getByRole('listitem').filter({ hasNotText: 'Deleted' });

// Diejenigen filtern, die ein bestimmtes untergeordnetes Element enthalten
page.getByRole('listitem').filter({ has: page.getByRole('button') });

// Diejenigen filtern, die kein bestimmtes untergeordnetes Element enthalten
page.getByRole('listitem').filter({ hasNot: page.getByTestId('badge') });

.locator() zum Lokalisieren von untergeordneten Elementen

Beispiel

// Zuerst den Listencontainer lokalisieren, dann darin Buttons finden
const list = page.getByTestId('todo-list');
const deleteBtn = list.locator('button.delete');
await deleteBtn.click();

// Mehrstufige Verschachtelung
page
  .getByRole('dialog')
  .locator('div.content')
  .locator('button')
  .filter({ hasText: 'Confirm' })
  .click();

.and() und .or() Logische Kombinationen (1.63+)

Beispiel

// Beide Bedingungen gleichzeitig erfüllen
const btn = page.getByRole('button')
  .und(page.getByText('Submit'));

// Eine der beiden Bedingungen erfüllen
const target = page.getByText('EXAMPLE')
  .oder(page.getByTitle('EXAMPLE'));

Zusammenfassung der Priorität der Locator-Strategie

Geordnet von der höchsten zur niedrigsten Empfehlung:

PrioritätMethodeVerwendungsbedingung
1 (Am meisten empfohlen)getByRole()Element hat eine klare ARIA-Rolle
2getByLabel()Formularelement hat ein zugehöriges Label
3getByPlaceholder()Eingabefeld hat einen Platzhalter
4getByText()Element hat klaren Textinhalt
5getByAltText()Bild hat alt-Attribut
6getByTitle()Element hat title-Attribut
7 (Fallback)getByTestId()Wenn die Lokalisierung mit den oben genannten Methoden nicht möglich ist
8 (Letzter Ausweg)locator()CSS-Selektoren / XPath
Weitere Erweiterungen