getByRole in Playwright: Elemente so finden, wie Nutzer sie sehen

Wer von Selenium oder Cypress zu Playwright wechselt, greift oft automatisch zu CSS-Selektoren und IDs. Das funktioniert – aber Playwright empfiehlt einen anderen Weg: getByRole().

Statt nach Klassen oder Strukturen im HTML zu suchen, beschreibt ein Rollen-Locator, was ein Element ist und wie es heißt: „der Button Speichern“, „das Textfeld E-Mail-Adresse“. Solche Locators sind gut lesbar und überstehen Umbauten am Layout deutlich besser.

In diesem Beitrag zeige ich dir anhand einer neuen Testlab-Komponente, siehe Abschnitt 9, die wichtigsten Erkenntnisse – inklusive zweier typischer Stolperfallen.

Vorbereitung

Als Testobjekt dient die neue Komponente „Playwright getByRole Demo“ (Abschnitt 9) in meinem Testlab.

Sie enthält ein kleines Formular „Kundenkonto anlegen“ mit:

  • einem Eingabefeld E-Mail-Adresse und einer Auswahlliste Land
  • zwei Radiobuttons Privatkunde / Geschäftskunde und einer Checkbox Newsletter abonnieren
  • einem Link Datenschutzerklärung
  • den Buttons Speichern, Speichern als Entwurf und Abbrechen
  • einem Statusbereich, der das Ergebnis der letzten Aktion anzeigt

Der gesamte Bereich hat die ID st-getbyrole-demo-2026-container. Wie schon beim Timeout-Beispiel suchen wir alle Elemente innerhalb dieses Containers:

const demo = page.locator('#st-getbyrole-demo-2026-container');

Das zeigt gleich eine wichtige Erkenntnis: getByRole() lässt sich problemlos mit anderen Locators verketten. Der Container wird per ID gefunden, alles darin per Rolle.

Was ist eine Rolle?

Rollen stammen aus der Barrierefreiheit (ARIA). Screenreader und andere Hilfstechnologien lesen eine Webseite nicht als HTML-Code, sondern als Baum aus Rollen und Namen: „Button, Speichern“ oder „Link, Datenschutzerklärung“.

Ein Rollen-Locator besteht deshalb fast immer aus zwei Teilen:

  • Rolle: Um welche Art von Element handelt es sich?
  • Name (accessible name): Wie heißt das Element? Meistens der sichtbare Text, das zugehörige Label oder ein aria-label.

Die meisten HTML-Elemente haben ihre Rolle bereits eingebaut. Du musst im Code also nichts ergänzen:

  • <button> → button
  • <a href="..."> → link
  • <input type="text">, <input type="email">, <textarea> → textbox
  • <input type="checkbox"> → checkbox, <input type="radio"> → radio
  • <select> → combobox
  • <h1> bis <h6> → heading
  • <tr> / <td> → row / cell

Playwright kennt zwar sehr viele Rollen, im Alltag kommst du aber mit dieser kurzen Liste weit.

Beispiel 1: Ein Name passt auf zwei Buttons

Wir wollen auf „Speichern“ klicken mit:

await demo.getByRole('button', { name: 'Speichern' }).click();

Dieser Test schlägt fehl.

Playwright meldet eine strict mode violation: Der Locator passt auf zwei Elemente. Der Grund: Der Name wird standardmäßig als Teilstring ohne Beachtung der Groß-/Kleinschreibung verglichen. „Speichern“ steckt auch in „Speichern als Entwurf“.

Die Lösung ist die Option exact:

Jetzt findet Playwright genau einen Button und der Test besteht.

Merke: Ähnlich benannte Elemente sind der häufigste Grund für Probleme mit getByRole(). Mit exact: true oder einem regulären Ausdruck wie /^Speichern$/ wird der Vergleich eindeutig.

Beispiel 2: Ein Formular nur mit Rollen ausfüllen

Für Formularelemente nutzt Playwright das zugehörige <label> als Namen. Damit lässt sich unser komplettes Formular ohne eine einzige ID ausfüllen:

Achte auf die passende Aktion zur Rolle: fill() für Textfelder, selectOption() für Auswahllisten und check() für Checkboxen und Radiobuttons. check() ist dabei robuster als click(), weil Playwright anschließend prüft, ob das Element wirklich angehakt ist.

Siehe da, der Test besteht:

Beispiel 3: Überschriften, Links und Statusmeldungen

Übrigens: Auch Inhalte, die nicht klickbar sind, lassen sich über Rollen ansprechen:

Zwei Details sind hier interessant:

  • Mit level grenzt du Überschriften auf eine Ebene ein – hier <h3>.
  • Der Statusbereich trägt das Attribut role="status". Weil es auf der Seite nur einen davon gibt, brauchen wir nicht einmal einen Namen.

Beispiel 4: getByRole findet ein sichtbares Element nicht

Jetzt klicken wir auf „Abbrechen“:

Dieser Test schlägt fehl – obwohl „Abbrechen“ auf der Seite deutlich zu sehen ist und wie ein Button aussieht.

Ein Blick in den HTML-Code verrät den Grund: „Abbrechen“ ist kein <button>, sondern ein <div> mit einem Klick-Handler.

Optisch ein Button, technisch keiner. Für Playwright – und für einen Screenreader – existiert hier kein Button, sodass der Test fehlschlägt.

Du erinnerst dich vllt. an den Action-Timeout aus dem letzten Beitrag: Ein höherer Timeout hilft auch hier nicht. Es gibt zwei Wege:

  • Besser: Das Entwicklungsteam ersetzt das <div> durch einen echten <button>. Damit ist der Test grün und die Seite gleichzeitig barrierefreier.
  • Übergangslösung: Im Test auf einen anderen Locator ausweichen, z. B. demo.getByText('Abbrechen', { exact: true }).

Merke: Wenn getByRole() ein sichtbares Element nicht findet, hast du oft nicht nur ein Testproblem, sondern einen echten Barrierefreiheits-Fehler entdeckt.

Wann getByRole nicht die beste Wahl ist

getByRole() sollte deine erste Wahl sein, aber nicht deine einzige:

  • Wechselnde Texte: Zeigt ein Button den aktuell gewählten Wert an (z. B. „Hell“ oder „Dunkel“), bindest du den Locator an Testdaten. Ändert sich der Wert, bricht der Test. Hier ist eine stabile ID oder ein data-testid besser.
  • Icons ohne Namen: Ein Icon-Button ohne Text und ohne aria-label hat keinen Namen. Auch das ist ein Hinweis für das Entwicklungsteam.
  • Versteckte Elemente: Standardmäßig berücksichtigt getByRole() nur Elemente, die im Accessibility-Baum sichtbar sind.

Tipps: Rolle und Namen schnell herausfinden

  • Playwright Codegen / Inspector: Mit npx playwright codegen und der Funktion „Pick locator“ schlägt dir Playwright für ein Element automatisch einen Locator vor – meistens bereits mit getByRole().
  • Browser-DevTools: In Chrome zeigt der Bereich „Accessibility“ im Elements-Tab für jedes Element Rolle und Namen an.

Fazit

Mit getByRole() beschreibst du Elemente nicht über ihren technischen Aufbau, sondern über ihre Bedeutung für den Nutzer. Das macht deine Tests lesbarer und unempfindlicher gegenüber Änderungen an CSS-Klassen oder Seitenstruktur.

Die Beispiele aus dem Testlab zeigen aber auch: Ganz ohne Nachdenken geht es nicht. Ähnlich benannte Elemente brauchen einen exakten Vergleich, und nicht jedes Element, das wie ein Button aussieht, ist auch einer. Gerade diese Fälle sind wertvoll, denn sie decken oft Schwächen in der Barrierefreiheit der Anwendung auf. 

Weiterführende Links

Über mich

Dieser Beitrag wurde veröffentlicht .

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Bitte füllen Sie dieses Feld aus.
Bitte füllen Sie dieses Feld aus.
Bitte gib eine gültige E-Mail-Adresse ein.
Sie müssen den Bedingungen zustimmen, um fortzufahren.