Echivalentul lui waitForVisible/waitForElementPresent în testele Selenium WebDriver folosind Java? (Programare, Java, Selenium, Webdriver, Selenium Webdriver, Selenium Ide)

Jonik a intrebat.

În cazul testelor Selenium „HTML” (create cu Selenium IDE sau manual), puteți utiliza unele comenzi foarte utile cum ar fi WaitForElementPresent sau WaitForVisible.

<tr>
    <td>waitForElementPresent</td>
    <td>id=saveButton</td>
    <td></td>
</tr>

Atunci când codificați teste Selenium în Java (Webdriver / Selenium RC – nu sunt sigur de terminologia de aici), există ceva similar încorporat?

De exemplu, pentru a verifica dacă un dialog (care durează ceva timp să se deschidă) este vizibil…

WebElement dialog = driver.findElement(By.id("reportDialog"));
assertTrue(dialog.isDisplayed());  // often fails as it isn't visible *yet*

Care este cea mai curată robustă mod de a codifica o astfel de verificare?

Adăugarea Thread.sleep() peste tot ar fi urât și fragil, iar rularea propriilor bucle while pare destul de neîndemânatică…

Comentarii

5 răspunsuri
Petr Janeček

Așteptări implicite și explicite

Așteptare implicită

O așteptare implicită înseamnă să îi spui lui WebDriver să cerceteze DOM pentru o anumită perioadă de timp atunci când încearcă să găsească unul sau mai multe elemente, dacă acestea nu sunt disponibile imediat. Setarea implicită este 0. Odată setată, așteptarea implicită este setată pentru toată durata de viață a instanței obiectului WebDriver.

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

Așteptare explicită + Condiții așteptate

O așteptare explicită este un cod pe care îl definiți pentru a aștepta ca o anumită condiție să apară înainte de a continua în cod. Cel mai rău caz în acest sens este Thread.sleep(), care stabilește condiția la o perioadă de timp exactă pentru așteptare. Există câteva metode de comoditate furnizate care vă ajută să scriețicod care va aștepta doar atât timp cât este necesar. WebDriverWait în combinație cu ExpectedCondition este o modalitate prin care acest lucru poate fi realizat.

WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(
        ExpectedConditions.visibilityOfElementLocated(By.id("someid")));

Comentarii

  • Este ExpectedConditions o clasă sau o interfață? Dacă da, ce pachet ar trebui să fie importat pentru aceasta? –  > Por Ripon Al Wasim.
  • @RiponAlWasim Probabil că știți acum, dar încerc să răspund la toate întrebările… După cum se poate vedea în JavaDoc, este o clasă cu metode statice și este conținută în org.openqa.selenium.support.ui pachet. –  > Por Petr Janeček.
  • Deci, așteptările implicite se aplică și elementelor pe care s-a încercat să se facă clic, dar care sunt încă dezactivate? Să zicem că fac clic pe un buton pentru a face să apară un alt buton. Apoi încerc să dau clic pe acest alt buton. Apoi WebDriver își dă seama că acest alt buton este dezactivat. Ce se întâmplă acum? Aruncă o excepție sau așteaptă numărul de secunde configurat în așteptarea implicită pentru driverul curent și apoi încearcă să facă din nou clic pe el? –  > Por Mercious.
  • @Mercious Ați putea încerca cu ușurință acest lucru singur, dar vă voi economisi timpul – se aruncă o excepție. Butonul ar fi găsit, deci WebDriver NU așteaptă implicit ca acesta să devină activat. Trebuie să scrieți o așteptare explicită pentru acest lucru. –  > Por Petr Janeček.
  • @Slanec Aș fi făcut acest lucru dacă mi-ar fi fost ușor să testez. Când ceva de genul acesta eșuează, abia pot ghici ce nu merge bine, deoarece site-ul web pe care îl testez utilizează și o mulțime de scripturi java … haotice. Încercam să devin clar în legătură cu acest lucru. Vă mulțumesc pentru răspunsul dvs. privind clarificarea acestui aspect, ajută foarte mult. –  > Por Mercious.
user1710861
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By.id("myDynamicElement")));

Acest lucru așteaptă până la 10 secunde înainte de a arunca o excepție TimeoutException sau dacă găsește elementul îl va returna în 0 – 10 secunde. În mod implicit, WebDriverWait apelează ExpectedCondition la fiecare 500 de milisecunde până când se întoarce cu succes. O întoarcere cu succes pentru tipul ExpectedCondition este o valoare de întoarcere booleană adevărată sau o valoare de întoarcere nu nulă pentru toate celelalte tipuri de ExpectedCondition.


WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

Elementul este „Clickable” – este afișat și activat.

De la WebDriver docs: Explicit and Implicit Waits (Așteptări explicite și implicite)

Mike Kwan

Ei bine, probabil că, de fapt, nu doriți ca testul să ruleze la nesfârșit. Doriți doar să așteptați o perioadă mai lungă de timp înainte ca biblioteca să decidă că elementul nu există. În acest caz, cea mai elegantă soluție este să folosiți așteptarea implicită, care este concepută tocmai pentru acest lucru:

driver.manage().timeouts().implicitlyWait( ... )

Comentarii

  • Mulțumesc! Acest lucru pare perfect… cu excepția faptului că pentru waitForVisible nu funcționează. Presupun că WebDriver aplică timeout-ul în findElement()dar ce se întâmplă dacă se returnează cu succes imediat șiisDisplayed ulterior eșuează deoarece nu este vizibil încă (a se vedea codul Java în cauză)…? –  > Por Jonik.
  • @Jonik: Am răspuns într-un fel la această întrebare înainte aici: stackoverflow.com/a/6379817. Trucul este să folosiți WebDriverWait pe care specificați un callback care este interogat. Este similar cu polling-ul de sine stătător, dar îl abstractizează. De asemenea, se ocupă și de timeout-uri. Codul din acel răspuns trebuie adaptat puțin, dar ar trebui să înțelegeți ideea. –  > Por Mike Kwan.
  • Tocmai am verificat că acest lucru funcționează într-adevăr foarte bine ca waitForElementPresent echivalent (direct). Mulțumesc, mă voi uita la celălalt răspuns mâine (prea obosit să mă gândesc acum) 🙂 –  > Por Jonik.
  • Indiciu post-mortem: așteptarea implicită strică ExpectedConditions, care utilizează driver.findElement în mod intern. –  > Por Hubert Grzeskowiak.
Veeksha A V

O altă modalitate de a aștepta maximum o anumită perioadă de timp, de exemplu 10 secunde, pentru ca elementul să fie afișat, după cum urmează:

(new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver d) {
                return d.findElement(By.id("<name>")).isDisplayed();

            }
        });

Ripon Al Wasim

Pentru fiecare element în parte, se poate utiliza codul de mai jos:

private boolean isElementPresent(By by) {
        try {
            driver.findElement(by);
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }
for (int second = 0;; second++) {
            if (second >= 60){
                fail("timeout");
            }
            try {
                if (isElementPresent(By.id("someid"))){
                    break;
                }
                }
            catch (Exception e) {

            }
            Thread.sleep(1000);
        }

Comentarii

  • Acest cod conține atât de multe mirosuri încât este greu de luat în serios. 1. 1. Refaceți roata. Vezi alte răspunsuri pentru așteptare încorporată. 2. Thread.sleep este urât și predispus la erori. 3. La fel ca și prinderea excepției generice. 4. „if” fără paranteze curly brackets, care este o sursă comună de erori. 5. Ce este „fail()”? Mai bine aruncați o excepție semnificativă în teste. 6. Scoateți condiția de buclă din instrucțiunea „for”. 7. Scrierea mai multor declarații într-o singură linie poate părea mișto, dar nu este, de fapt. De asemenea, indentarea este stricată pe acest post. –  > Por Hubert Grzeskowiak.
  • Sunt de acord. Cea mai bună soluție este să folosiți Explicit wait (WebDriverWait). Utilizarea Thread.sleep() nu este bună. Pe baza comentariului dvs. am reorganizat codul cu paranteze curly braces în declarația if, astfel încât a devenit mai ușor de citit. Vă mulțumim pentru comentariul dumneavoastră. –  > Por Ripon Al Wasim.