Frage von sommerli, 58

Codeception: Warum findet es den Button nicht?

Hallo und zwar habe ich eine Frage. Ich hab mit Codeception einen Akzeptanztest erstellt, um die Logoutfunktion zu testen, jedoch findet es den Logout Button in der Navigation nicht

Fehlermeldung: No links containing text 'Logout (stefanie)' were found in page /index.php?r=site%2Findex

hier der Code von der Seite

<div class="wrap">
<nav id="w0" class="navbar-inverse navbar-fixed-top navbar" role="navigation"><div class="container"><div class="navbar-header"><button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#w0-collapse"><span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span></button><a class="navbar-brand" href="/index.php">Rechnen & Denken ist super</a></div><div id="w0-collapse" class="collapse navbar-collapse"><ul id="w1" class="navbar-nav navbar-right nav"><li class="active"><a href="/index.php?r=site%2Findex">Startseite</a></li>
<li><a href="/index.php?r=site%2Fabout">Über uns</a></li>
<li><a href="/index.php?r=site%2Fcontact">Kontakt</a></li>
<li><form action="/index.php?r=site%2Flogout" method="post">
<input type="hidden" name="_csrf" value="bS5HdWgwX1o5GQkAUVIwLQ5PFQ8NYRwvF2wCEi9EGRMJZTQ7I1oHMw=="><button type="submit" class="btn btn-link" name="logout-button">Logout (stefanie)</button></form></li></ul></div></div></nav>

Testcode

<?php

$I = new AcceptanceTester($scenario);
$I->login('stefanie', 'stefanie');
$I-> wantTo ('logout');
$I-> lookForwardTo ('logout');

$I-> amOnPage ('/index.php?r=site%2Findex');

$I-> seeLink ('Logout (stefanie)');
$I-> click ('Logout (stefanie)');


$I->see('Login');

?>
Antwort
von bergerle, 17

Ich kenn mich mit codeception nicht aus, hätte jetzt aber spontan vermutet, dass es daran liegt, dass du nach einem link suchst, das Element aber ein Button ist. 

Antwort
von Noeru, 41

Doofe Frage, aber kannst Du nicht über das Attribut @name gehen.
Der Button hat eine wunderschöne, eindeutige ID. Wenn Du über den gehen könntest, hast Du auch ein dynamischen Testdesign. So ist es nur statisch.

Kommentar von sommerli ,

Hab ich schon probiert.. Funktioniert leider auch nicht :/

Kommentar von Noeru ,

Hast Du die Möglichkeit über die HTML-Struktur zum Button zu navigieren?

z.B. ".//[@name='logout-button']"
Oder, falls Du doch über den Text gehen willst, versuch den Button in der HTML-Struktur auf die Form zu tracken, die den Button enthält (im Beispiel mit x markiert):

.//*[@id='x']//type[contains(text(),'Logout (stephanie)')]

Kommentar von sommerli ,

Könntest du mir das ein bisschen ausführlicher erklären? Versteh es ehrlich gesagt nicht ganz

Kommentar von Noeru ,

Okay, gerne. 

Ich denke, Du weißt wie HTML aufgebaut ist. Es gibt immer eine Form (@form oder @body), die alle anderen Webelemente enthalten. Sagen wir, wir haben folgende Struktur:

<body id="Beispielbody" blahblah Attribute blah blah
  <div id="sales" blah blah </div>
  <div id="wrapper" blah blah </div>
  [...]
  <div class="blahblah">
  <button type="submit" name="Kommentar abschicken" </button>
  </div>
  [...]
  </div>
  </div>
</body>

Unsere Seite sieht so aus. Jetzt möchtest Du, dass Dein Skript auf den Button "Kommentar abschicken" klickt.

Um das zu machen, hast Du sechs Möglichkeiten:

1) Du navigierst in der HTML-Struktur so lange runter, bis Du beim Button angelangt bist. Also in dem Beispiel so: 

xpath://body[@id="Beispielbody"]/div/div/[...]/div/button

Diese Art der Adressierung ist halb-statisch, denn sobald sich etwas an der HTML-Struktur ändert, d.h. kommt z.B. noch eine Tabelle vor eines der <div>, funktioniert Dein Skript nicht mehr, weil der Button nicht mehr unter gegebener Struktur ist.

2)Du navigierst zum kleinsten gemeinsamen Nenner des Buttons und der Struktur herunter, d.h. Du gehst zu der Form, die den Button enthält und adressierst ihn darüber. z.B.

  xpath://div[@class="blahblah"]/button

Das funktioniert wunderbar, solange im <div> "blahblah" nur ein einziger Button ist. Wenn es zwei gibt und Du möchtest auf den ersten Klicken, könntest Du folgendes machen:

xpath://div[@class="blahblah"]/button[1]

Das ist aber wie in Beispiel 1) beschrieben halb-statisch, d.h. ist der Button, auf den Du klicken willst, plötzlich nicht mehr der erste Button, sondern der zweite, funktioniert Dein Skript nicht mehr und richtig und stattdessen wird der Button geklickt, der nun an erster Stelle steht.

Deswegen kannst Du 3) folgendes machen:

xpath://div[@class="blahblah"]//button[@type="submit")]

Dieser Ausdruck sagt im Endeffekt "Suche ein <div> mit dem Attribut class welches den Namen "blahblah" hat und suche darunter einen Button mit einem type, der "submit" entspricht. Das ist relativ dynamisch. Wenn es zwei Buttons in diesem <div> gibt, die ein Attribut @type="submit" haben, könnte es Probleme geben. Aber das ist ziemlich unwahrscheinlich.

Die 4) Variante ist fast genauso wie die 3), nur nutzen wir hierfür die Funktion text(). Sie erlaubt es uns, nicht nach Attributen zu suchen, sondern nach Texten. z.B. Buttonnamen oder Labels. Möchten wir den Button mit dieser Funktion adressieren, würde das so aussehen:

xpath://div[@class=blahblah"]//button[text()="Kommentar abschicken"]

Die letzte Möglichkeit ist im Endeffekt nur ein Tipp bzw. wie man es auch machen kann. In unserem Beispiel hat der Button mindestens ein Attribut, welches es eindeutig macht. Deswegen ist es gar nicht notwendig, dass wir zur übergeordeten Form (<div="blahblah") gehen. Man könnte also auch folgendes schreiben:

xpath://button[@type="submit"]

Oder

xpath://button[text()="Kommentar abschicken"]

Ich hoffe, das hat ein wenig geholfen.

Wenn Du magst, schick mir eine private Message und wir können da näher drauf eingehen :)

LG
Noeru

Kommentar von sommerli ,

Vielen lieben Dank für deine Erklärung (: den Html Code hat jemand anderes geschrieben und wollte da nichts zerschießen. Hab aber eine andere Lösung gefunden, einfach das
$I-> seeLink weggelassen und schon ging es.

Kommentar von Noeru ,

Aah, wtf :D naja, kurze Exkursionen in xPath schaden nie~! Schön, dass a funktioniert!

Keine passende Antwort gefunden?

Fragen Sie die Community