2013-01-22 4 views
10

Oltre a utilizzare sleep() nel mio test, mi chiedo se qualcuno conosce una strategia migliore per attendere esplicitamente l'invio di un modulo (POST) da completare prima continuando con le mie affermazioni. Ecco una versione molto condensata di come appare il mio test, usando phpunit insieme php-webdriver da Facebook).php-webdriver: attendere la risposta del browser dopo aver inviato il modulo utilizzando 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

Quindi, quando si esegue questo codice ora, l'url nella penultima riga (l'assert) fornisce http://example.com/login invece di http://example.com/account? Presumibilmente il server Selenium dovrebbe aspettare da solo fino a caricare la pagina prima di cercare l'elemento. L'eccezione a ciò sono le richieste asincrone, ma la tua sembra piuttosto sincrona. Intendiamoci, sto usando PHPUnit_Selenium per guidare Selenium – qrazi

+0

Esattamente. In effetti posso fare uno screenshot anche in quel momento, e vedere che sono ancora su example.com/login, ma se dormo per 1 secondo, passa l'assert e lo screenshot mostra che la pagina è ora ad esempio. com/account. Ho letto che PHPUnit_Selenium non era del tutto all'altezza di eseguire Selenium 2 (ovvero il webdriver), ecco perché ho seguito l'approccio sopra descritto. –

risposta

0

Invece di click() dovrebbe essere possibile utilizzare clickAndWait(), al fine di attendere fino a quando la pagina successiva è stata caricata.

+0

Non sono sicuro che funzioni con php-webdriver. Ottengo il seguente errore: "Eccezione: clickAndWait non è un comando di webdriver valido." –

1

È possibile utilizzare Implicit Wait and Explicit Wait per attendere un elemento Web particolare finché non viene visualizzato nella pagina. Il periodo di attesa che puoi definire dipende dall'applicazione.

Attendere esplicito:

Un attese esplicite è il codice si definisce di aspettare per una certa condizione che si verifichi prima di procedere ulteriormente nel codice. Se la condizione raggiunta, terminerà l'attesa e proseguirà con le ulteriori fasi.

Codice:

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

O

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

Questa attende fino a 30 secondi prima di lanciare un TimeoutException o se trova l'elemento tornerà in 0 - 30 secondi. WebDriverWait di default chiama la ExpectedCondition ogni 500 millisecondi finché non ritorna correttamente. Un risultato positivo per il tipo ExpectedCondition è Boolean return true o non null valore di ritorno per tutti gli altri tipi di ExpectedCondition.

È possibile utilizzare la classe ExpectedConditions come necessario per l'applicazione.

Attendere implicito:

un'attesa implicita è quella di dire WebDriver interroga il DOM per un certo periodo di tempo quando si cerca di trovare un elemento o gli elementi se non sono immediatamente disponibili

Codice:

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

una cosa da tenere a mente è che una volta che l'attesa implicita è impostata - rimarrà per la vita della istanza di oggetto WebDriver

Per maggiori informazioni utilizza questo link http://seleniumhq.org/docs/04_webdriver_advanced.jsp

+6

Mi stavo chiedendo specificamente una soluzione PHP che utilizza php-webdriver. –

2

Okay, so che questa è una domanda molto vecchio, ma come mi sono imbattuto su di essa tramite Google Spero che questo può ancora essere utile per qualcuno (forse anche il PO? :-)).

Dopo aver cercato e letto alcuni articoli e messaggi su Google Code, ho trovato una soluzione che ritengo sia abbastanza brutta, ma non c'è davvero una buona alternativa. È possibile leggere here che è impossibile per WebDriver rilevare quando la pagina è stata caricata. Quindi, dobbiamo tornare ad aspettare. Ora, l'OP utilizza il PHP WebDriver di Facebook, che non include le utilità di attesa AFAIK, ma quando si utilizza this maintained clone, si ottiene un'implementazione di WebDriverWait.

Ora la domanda è: cosa aspettiamo? Puoi aspettare che l'URL cambi, ma questo non è in alcun modo un approccio affidabile poiché la pagina probabilmente non è ancora stata caricata quando l'URL è già cambiato. Opzione successiva: attendi che un elemento che conosci sia presente nella pagina da caricare. Funzionerà, ma cosa succede se si desidera avere un approccio più generico? Fortunatamente, ho letto una buona idea in the thread che ho menzionato sopra. È possibile attendere la scomparsa di un elemento su entrambe le pagine e riapparire, ad esempio il piè di pagina.

L'ho implementato proprio ora e sembra funzionare. Sotto la funzione può essere passato il tuo $session e tornerà solo quando viene caricata la nuova pagina (o almeno, il piè di pagina è nuovamente disponibile).

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"))); 
      } 
     ); 
} 

Ovviamente è possibile modificare il selettore o utilizzare qualche altro elemento, l'idea rimane la stessa.

Spero che aiuti! Saluti!

19

php-webdriver da Facebook è stato riscritto nel giugno 2013. È possibile attendere l'URL facilmente come questo.

// 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

Cosa succede se l'url viene creato dinamicamente? ad esempio: site.com/item?id=123&color=black&size=small – Purefan

+1

Abbina l'URL in base all'espressione regolare. – whhone

+0

Una buona risposta almeno per l'attesa! –