2013-01-22 6 views
10

Neben der Verwendung von sleep() in meinem Test frage ich mich, ob jemand eine bessere Strategie kennt, um explizit auf das Senden eines Formulars (POST) zu warten weiter mit meinen Behauptungen. Hier ist eine sehr verkürzte Version von wie mein Test aussieht, mit phpunit zusammen php-webdriver von Facebook).php-webdriver: warte auf die Browserantwort nach dem Absenden des Formulars mit click()

function test_form_submission() 
{ 
    // setup 
    $web_driver = new WebDriver(); 
    $session = $web_driver->session(); 
    $session->open('http://example.com/login'); 

    // enter data 
    $session->element('css selector', 'input[name=email]')->value(array('value' => str_split('[email protected]'))); 
    $session->element('css selector', 'input[name=password]')->value(array('value' => str_split('testpassword'))); 

    // click button to submit form 
    $session->element('css selector', 'button[name=submit]')->click(); 

    // How do I wait here until the click() above submits the form 
    // so I can check that we correctly arrives at the destination below 
    // without resorting to sleep()? 

    // Confirm that login was successful because we landed on account page 
    $this->assertSame('http://example.com/account', $session->url()); 

    // teardown 
    $session->close(); 
} 
+1

Also, wenn Sie diesen Code jetzt ausführen, die URL in der vorletzten Zeile (die Assertion) gibt http://example.com/login statt http://example.com/account? Vermutlich sollte der Selenium-Server warten, bis die Seite geladen ist, bevor er nach dem Element sucht. Die Ausnahme davon sind asynchrone Anfragen, aber Ihre sieht ziemlich synchron aus. Wohlgemerkt, ich benutze PHPUnit_Selenium, um Selenium – qrazi

+0

Exakt zu fahren. Tatsächlich kann ich in diesem Moment auch einen Screenshot machen und sehen, dass ich immer noch auf example.com/login bin, aber wenn ich 1 Sekunde lang schlafe, vergeht die Assert, und der Screenshot zeigt, dass die Seite jetzt ein Beispiel ist. com/Konto. Ich habe gelesen, dass PHPUnit_Selenium nicht ganz auf Selenium 2 (aka Webdriver) läuft, weshalb ich mit dem obigen Ansatz fortgefahren bin. –

Antwort

0

Statt click() sollte es möglich sein clickAndWait() zu verwenden, um bis zur nächsten Seite geladen ist, zu warten.

+0

Ich bin mir nicht sicher, dass das mit php-webdriver funktioniert. Ich erhalte den folgenden Fehler: "Ausnahme: ClickAndWait ist kein gültiger Webdriver-Befehl." –

1

Sie können Implicit Wait and Explicit Wait verwenden, um auf ein bestimmtes Webelement zu warten, bis es auf der Seite angezeigt wird. Die Wartezeit, die Sie definieren können, hängt von der Anwendung ab.

Explicit Warten:

eine explizite wartet ist Code, den Sie definieren, zu warten, bis eine bestimmte Bedingung, bevor Sie fortfahren weiter im Code auftreten. Wenn die Bedingung erfüllt ist, wird die Wartezeit beendet und die weiteren Schritte ausgeführt.

Code:

WebDriverWait wait = new WebDriverWait(driver,30); 
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(strEdit))); 

Oder

WebElement myDynamicElement = (new WebDriverWait(driver, 30)) 
.until(new ExpectedCondition<WebElement>(){ 
@Override 
public WebElement apply(WebDriver d) { 
    return d.findElement(By.id("myDynamicElement")); 
}}); 

Diese wartet bis zu 30 Sekunden, bevor Sie einen Timeout werfen oder wenn es das Element findet kehrt es in 0-30 Sekunden. WebDriverWait ruft die ExpectedCondition standardmäßig alle 500 Millisekunden auf, bis sie erfolgreich zurückgegeben wird. Eine erfolgreiche Rückgabe ist für den ExpectedCondition-Typ Boolean return true oder nicht null return value für alle anderen ExpectedCondition-Typen.

Sie können die ExpectedConditions-Klasse verwenden, die Sie für die Anwendung benötigen.

Implizite Warten:

Eine implizite Warten ist WebDriver zu sagen, das DOM für eine gewisse Zeit abzufragen, wenn man versucht, ein Element oder Elemente zu finden, wenn sie

-Code nicht sofort verfügbar sind:

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); 

Eine Sache im Auge zu behalten ist, dass, sobald die implizite Warte gesetzt - es ist für die gesamte Lebensdauer der WebDriver Objektinstanz bleibt

Für weitere Informationen nutzen Sie diesen Link http://seleniumhq.org/docs/04_webdriver_advanced.jsp

+6

Ich fragte speziell nach einer PHP-Lösung, die PHP-Webdriver verwendet. –

2

Okay, so dass ich weiß, dass dies eine sehr alte Frage, aber wie ich auf sie durch Google stolperte ich hoffe, dass dies immer noch für jemanden nützlich sein kann (vielleicht sogar der OP? :-)).

Nach einigem Suchen und Lesen von Artikeln und Nachrichten auf Google Code fand ich eine Lösung, die ich für ziemlich hässlich halte, aber es gibt keine wirklich gute Alternative. Sie können here lesen, dass WebDriver unmöglich erkennen kann, wenn die Seite geladen wurde. Also müssen wir zum Warten zurückkehren. Nun verwendet das OP den Facebook WebDriver von Facebook, der keine wartenden Dienstprogramme AFAIK enthält, aber wenn Sie this maintained clone verwenden, erhalten Sie eine Implementierung von WebDriverWait.

Jetzt ist die Frage: Worauf warten wir? Sie könnten warten, bis sich die URL geändert hat, aber dies ist in keiner Weise ein zuverlässiger Ansatz, da die Seite wahrscheinlich noch nicht geladen ist, wenn sich die URL bereits geändert hat. Nächste Option: Warten Sie, bis ein Element, von dem Sie wissen, dass es auf der Seite geladen ist, angezeigt wird. Das wird funktionieren, aber was ist, wenn Sie einen allgemeineren Ansatz haben wollen? Zum Glück lese ich eine sehr gute Idee in the thread ich oben erwähnt. Sie können darauf warten, dass ein Element, das sich auf beiden Seiten befindet, verschwindet und wieder angezeigt wird, z. B. die Fußzeile.

Ich habe das gerade jetzt implementiert und es scheint zu funktionieren. Die unten angegebene Funktion kann an Ihre $session übergeben werden und wird erst zurückkommen, wenn die neue Seite geladen ist (oder zumindest die Fußzeile wieder verfügbar ist).

public static function waitForNextPage($pWDSession) { 
    $aWait = new PHPWebDriver_WebDriverWait($pWDSession); 
    // wait for footer to not be available anymore 
    $aWait->until(
      function($pWDSession) { 
       return (0 === count($pWDSession->elements(PHPWebDriver_WebDriverBy::CSS_SELECTOR, "#footer,#mx-footer"))); 
      } 
     ); 
    // wait for footer to be available again 
    $aWait->until(
      function($pWDSession) { 
       return (0 < count($pWDSession->elements(PHPWebDriver_WebDriverBy::CSS_SELECTOR, "#footer,#mx-footer"))); 
      } 
     ); 
} 

Sie können natürlich den Selektor ändern oder ein anderes Element verwenden, die Idee bleibt gleich.

Ich hoffe, es hilft! Prost!

19

php-webdriver von Facebook wurde im Juni 2013 neu geschrieben. Sie können auf die URL einfach so warten.

// wait for at most 10 seconds until the URL is 'http://example.com/account'. 
// check again 500ms after the previous attempt. 
$driver->wait(10, 500)->until(function ($driver) { 
    return $driver->getCurrentURL() === 'http://example.com/account'; 
}) 
+0

Was passiert, wenn die URL dynamisch erstellt wird? Beispiel: site.com/item?id=123&color=black&size=small – Purefan

+1

Ordnen Sie die URL dem regulären Ausdruck zu. – whhone

+0

Eine gute Antwort zumindest für Wartezeiten! –

Verwandte Themen