it-swarm.com.de

Wie kann ich den Selenium-WebDriver bitten, einige Sekunden in Java zu warten?

Ich arbeite an einem Java Selenium-WebDriver. Ich fügte hinzu 

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

und

WebElement textbox = driver.findElement(By.id("textbox"));

weil meine Anwendungen einige Sekunden benötigen, um die Benutzeroberfläche zu laden. Also habe ich 2 Sekunden implizit gewartet. aber ich habe Element-Textfeld konnte nicht gefunden werden

Dann füge ich Thread.sleep(2000); hinzu

Jetzt funktioniert es gut. Welcher ist ein besserer Weg? 

91
Prince

Nun, es gibt zwei Arten des Wartens: explizites und implizites Warten. Die Idee des expliziten Wartens ist

WebDriverWait.until(condition-that-finds-the-element);

Das Konzept des impliziten Wartens ist

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

Sie können Unterschiede in Details hier erhalten.

In solchen Situationen würde ich das explizite Warten bevorzugen (insbesondere fluentWait):

public WebElement fluentWait(final By locator) {
    Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
            .withTimeout(30, TimeUnit.SECONDS)
            .pollingEvery(5, TimeUnit.SECONDS)
            .ignoring(NoSuchElementException.class);

    WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
        public WebElement apply(WebDriver driver) {
            return driver.findElement(locator);
        }
    });

    return  foo;
};

Die fluentWait-Funktion gibt Ihr gefundenes Web-Element zurück Aus der Dokumentation fluentWait: Eine Implementierung der Wait-Schnittstelle, deren Timeout und Abrufintervall im laufenden Betrieb konfiguriert werden kann . Jede FluentWait-Instanz definiert das Maximum Zeit, um auf eine Bedingung zu warten, sowie die Häufigkeit, mit der die Bedingung überprüft werden soll. Darüber hinaus kann der Benutzer das Warten so konfigurieren, dass bestimmte Arten von Ausnahmen während des Wartens ignoriert werden, z. B. NoSuchElementExceptions bei der Suche nach einem Element auf der Seite. Details erhalten Sie hier

Die Verwendung von fluentWait ist in Ihrem Fall wie folgt:

WebElement textbox = fluentWait(By.id("textbox"));

Dieser Ansatz ist IMHO besser, da Sie nicht genau wissen, wie viel Zeit Sie warten müssen, und dass Sie im Abfrageintervall einen beliebigen Zeitpunkt festlegen können, welche Element-Präsenz durch . Überprüft wird.

110

Wenn Sie webdriverJs (node.js) verwenden,

driver.findElement(webdriver.By.name('btnCalculate')).click().then(function() {
    driver.sleep(5000);
});

Der obige Code bewirkt, dass der Browser nach dem Klicken auf die Schaltfläche 5 Sekunden wartet.

16
Anup

Dieser Thread ist etwas älter, aber ich dachte, ich würde das posten, was ich gerade mache (work in progress).

Obwohl ich immer noch auf Situationen stoße, in denen das System stark ausgelastet ist und wenn ich auf einen Submit-Button klicke (zB login.jsp), geben alle drei Bedingungen (siehe unten) true zurück, aber die nächste Seite (zB home.jsp) hatn Es wurde noch nicht mit dem Laden begonnen.

Dies ist eine generische Wartemethode, die eine Liste von ExpectedConditions annimmt. 

public boolean waitForPageLoad(int waitTimeInSec, ExpectedCondition<Boolean>... conditions) {
    boolean isLoaded = false;
    Wait<WebDriver> wait = new FluentWait<>(driver)
            .withTimeout(waitTimeInSec, TimeUnit.SECONDS)
            .ignoring(StaleElementReferenceException.class)
            .pollingEvery(2, TimeUnit.SECONDS);
    for (ExpectedCondition<Boolean> condition : conditions) {
        isLoaded = wait.until(condition);
        if (isLoaded == false) {
            //Stop checking on first condition returning false.
            break;
        }
    }
    return isLoaded;
}

Ich habe verschiedene wiederverwendbare ExpectedConditions definiert (drei sind unten). In diesem Beispiel umfassen die drei erwarteten Bedingungen document.readyState = 'complete', kein "wait_dialog" und keine "Spinner" (Elemente, die angeben, dass asynchrone Daten angefordert werden).

Nur die erste kann generisch auf alle Webseiten angewendet werden.

/**
 * Returns 'true' if the value of the 'window.document.readyState' via
 * JavaScript is 'complete'
 */
public static final ExpectedCondition<Boolean> EXPECT_DOC_READY_STATE = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        String script = "if (typeof window != 'undefined' && window.document) { return window.document.readyState; } else { return 'notready'; }";
        Boolean result;
        try {
            result = ((JavascriptExecutor) driver).executeScript(script).equals("complete");
        } catch (Exception ex) {
            result = Boolean.FALSE;
        }
        return result;
    }
};
/**
 * Returns 'true' if there is no 'wait_dialog' element present on the page.
 */
public static final ExpectedCondition<Boolean> EXPECT_NOT_WAITING = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        Boolean loaded = true;
        try {
            WebElement wait = driver.findElement(By.id("F"));
            if (wait.isDisplayed()) {
                loaded = false;
            }
        } catch (StaleElementReferenceException serex) {
            loaded = false;
        } catch (NoSuchElementException nseex) {
            loaded = true;
        } catch (Exception ex) {
            loaded = false;
            System.out.println("EXPECTED_NOT_WAITING: UNEXPECTED EXCEPTION: " + ex.getMessage());
        }
        return loaded;
    }
};
/**
 * Returns true if there are no elements with the 'spinner' class name.
 */
public static final ExpectedCondition<Boolean> EXPECT_NO_SPINNERS = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        Boolean loaded = true;
        try {
        List<WebElement> spinners = driver.findElements(By.className("spinner"));
        for (WebElement spinner : spinners) {
            if (spinner.isDisplayed()) {
                loaded = false;
                break;
            }
        }
        }catch (Exception ex) {
            loaded = false;
        }
        return loaded;
    }
};

Abhängig von der Seite kann ich eine oder alle von ihnen verwenden:

waitForPageLoad(timeoutInSec,
            EXPECT_DOC_READY_STATE,
            EXPECT_NOT_WAITING,
            EXPECT_NO_SPINNERS
    );

Es gibt auch vordefinierte ExpectedConditions in der folgenden Klasse: org.openqa.Selenium.support.ui.ExpectedConditions

11
Jeff Vincent

Die Verwendung von Thread.sleep(2000); ist eine bedingungslose Wartezeit. Wenn Ihr Test schneller lädt, müssen Sie noch warten. Grundsätzlich ist implicitlyWait die bessere Lösung.

Ich verstehe jedoch nicht, warum implicitlyWait in Ihrem Fall nicht funktioniert. Haben Sie gemessen, ob findElement tatsächlich zwei Sekunden dauert, bevor eine Ausnahme ausgelöst wird? Wenn ja, können Sie versuchen, die bedingte Wartezeit von WebDriver wie in this answer zu verwenden?

8
Valentin

Ich benutze gerne individuelle Bedingungen. Hier ist etwas Code in Python:

def conditions(driver):
    flag = True
    ticker = driver.find_elements_by_id("textbox")
    if not ticker:
        flag = False
    return flag

... click something to load ...
self.wait = WebDriverWait(driver, timeout)
self.wait.until(conditions)

Wann immer Sie warten müssen, können Sie dies explizit tun, indem Sie das Vorhandensein eines bestimmten Elements prüfen (dieses Element kann von Seite zu Seite variieren). find_elements_by_id gibt die Liste zurück - leer oder nicht, Sie müssen nur überprüfen.

3
simno

klick scheint zu blockieren? - Wenn Sie WebDriverJS verwenden, warten Sie noch eine weitere Möglichkeit:

driver.findElement(webdriver.By.name('mybutton')).click().then(function(){
  driver.getPageSource().then(function(source) {
    console.log(source);
  });
});

Der obige Code wartet, nachdem auf die Schaltfläche geklickt wurde, bis die nächste Seite geladen wird. Anschließend wird der Quellcode der nächsten Seite angezeigt.

2
Dion
Thread.Sleep(5000);

Dies hat mir geholfen, aber die InterruptedException-Ausnahme muss beachtet werden.

try {
    Thread.Sleep(5000);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

OR

Wurfdeklaration hinzufügen:

public class myClass {
    public static void main(String[] args) throws InterruptedException
    { ... }

Ich würde die zweite vorziehen, da man sleep() so oft verwenden kann, wie es will, und die Wiederholung von try und catch block jedes Mal, wenn sleep() verwendet wurde, vermeidet.

1
Prasad Hajare

Manchmal schlägt das implizite Warten fehl und sagt, dass ein Element vorhanden ist, aber wirklich nicht.

Die Lösung besteht darin, die Verwendung von driver.findElement zu vermeiden und es durch eine benutzerdefinierte Methode zu ersetzen, die implizit eine explizite Wartezeit verwendet. Zum Beispiel:

import org.openqa.Selenium.NoSuchElementException;


public WebElement element(By locator){
    Integer timeoutLimitSeconds = 20;
    WebDriverWait wait = new WebDriverWait(driver, timeoutLimitSeconds);
    try {
        wait.until(ExpectedConditions.presenceOfElementLocated(locator));
    }
    catch(TimeoutException e){
        throw new NoSuchElementException(locator.toString());
    }
    WebElement element = driver.findElement(locator);
    return element;
}

Es gibt zusätzliche Gründe, um implizites Warten zu vermeiden, außer gelegentlichen Ausfällen (siehe link ).

Sie können diese "Element" -Methode auf dieselbe Weise wie driver.findElement verwenden. Zum Beispiel:

    driver.get("http://yoursite.html");
    element(By.cssSelector("h1.logo")).click();

Wenn Sie wirklich nur ein paar Sekunden auf die Fehlerbehebung oder eine andere seltene Gelegenheit warten möchten, können Sie eine Pausenmethode erstellen, die der von Selenium IDE ähnelt:

    public void pause(Integer milliseconds){
    try {
        TimeUnit.MILLISECONDS.sleep(milliseconds);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
0
JohnP2

Implizit warten und Thread.sleep Beide werden nur für die Synchronisation verwendet. Der Unterschied besteht jedoch darin, dass wir das gesamte Programm implizit abwarten können. Thread.sleep funktioniert jedoch nur für diesen einzelnen Code Wenn jedes Mal, wenn Ihre Webseite aktualisiert wird, bedeutet, verwenden Sie zu diesem Zeitpunkt Thread.sleep..it wird viel besser :)

Hier ist mein Code:

package beckyOwnProjects;

import Java.util.concurrent.TimeUnit;

import org.openqa.Selenium.By;
import org.openqa.Selenium.WebDriver;
import org.openqa.Selenium.WebElement;
import org.openqa.Selenium.firefox.FirefoxDriver;
import org.openqa.Selenium.interactions.Actions;

public class Flip {

    public static void main(String[] args) throws InterruptedException {
        WebDriver driver=new FirefoxDriver();
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES);
        driver.get("https://www.flipkart.com");
    WebElement ele=driver.findElement(By.cssSelector(".menu-text.fk-inline-block"));
    Actions act=new Actions(driver);
    Thread.sleep(5000);
    act.moveToElement(ele).perform();
    }

}
0
Beckham Vinoth

Manchmal scheint das implizite Warten überschrieben zu werden und die Wartezeit wird verkürzt. [@ eugene.polschikov] hatte eine gute Dokumentation über das Warum. Ich habe beim Testen und beim Codieren mit Selenium 2 festgestellt, dass implizite Wartezeiten gut sind, aber gelegentlich müssen Sie explizit warten. 

Es ist besser zu vermeiden, direkt nach einem Thread in den Schlaf zu rufen, aber manchmal gibt es keinen guten Weg. Es gibt jedoch auch andere Selenium-Wartemöglichkeiten, die helfen. waitForPageToLoad und waitForFrameToLoad haben sich als besonders nützlich erwiesen. 

0
BadgerAndK

Antwort : Warten Sie einige Sekunden, bevor die Elementsichtbarkeit mit Selenium WebDriver unter den folgenden Methoden durchläuft.

implicitlyWait () : Die WebDriver-Instanz wartet, bis die vollständige Seite geladen ist. Sie brauchen 30 bis 60 Sekunden, um die volle Seitenladung abzuwarten.

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

ExplicitlyWait WebDriverWait () : Die WebDriver-Instanz wartet, bis die vollständige Seite geladen ist.

WebDriverWait wait = new WebDriverWait(driver, 60);

wait.until(ExpectedConditions.visibilityOf(textbox));

driver.findElement(By.id("Year")).sendKeys(allKeys);

Hinweis : Bitte verwenden Sie ExplicitlyWait WebDriverWait (), um ein bestimmtes WebElement zu bearbeiten.

0
sandeep shewale

Implizites Warten: Wenn der Web-Treiber das implizite Warten aufgrund seiner Verfügbarkeit nicht sofort findet, wartet der WebDriver auf die angegebene Zeit und versucht nicht, das Element innerhalb des angegebenen Zeitraums erneut zu finden. Nach Ablauf der angegebenen Zeit wird versucht, das Element vor dem Auslösen der Ausnahme erneut zu suchen. Die Standardeinstellung ist Null. Sobald wir eine Zeit eingestellt haben, wartet der Web Driver auf den Zeitraum der WebDriver-Objektinstanz.

Explizites Warten: Es kann vorkommen, dass das Laden eines bestimmten Elements mehr als eine Minute dauert. In diesem Fall möchten Sie definitiv keine große Zeit für implizites Warten festlegen, da Ihr Browser dann für jedes Element die gleiche Zeit warten wird. Um dies zu vermeiden, können Sie einfach eine separate Zeit einplanen nur das erforderliche Element. Wenn Sie dem Browser folgen, wäre die implizite Wartezeit für jedes Element kurz und für ein bestimmtes Element groß.

0
Abhishek Singh