web-dev-qa-db-fra.com

Comment puis-je vérifier si une page est chargée complètement ou pas dans le pilote Web?

J'écris du code Java Webdriver pour automatiser mon application. Comment puis-je vérifier correctement si la page a été chargée ou non? L'application a également des appels Ajax.

J'ai déclaré une attente implicite pour WebDriver.

21
Raghubansh

Le sélénium le fait pour vous. Ou du moins, il fait de son mieux. Parfois, cela manque et vous devez l'aider un peu. La solution habituelle est Implicit Wait qui résout la plupart des problèmes.

Si vous savez vraiment ce que vous faites et pourquoi vous le faites, vous pourriez essayer d’écrire une méthode générique permettant de vérifier si la page est complètement chargée. Cependant, cela ne peut pas être fait pour tous les sites Web et pour toutes les situations.


Question connexe: Selenium WebDriver: attendez le chargement d’une page complexe avec JavaScript (JS) , consultez ma réponse à cet endroit.

Version plus courte: vous ne serez jamais sûr.

La charge "normale" est facile - document.readyState . Celui-ci est mis en œuvre par Selenium, bien sûr. Le problème, ce sont les requêtes asynchrones, AJAX, car on ne peut jamais dire si c'est fait pour le bien ou non. La plupart des pages Web actuelles ont des scripts qui fonctionnent à l'infini et interrogent le serveur à tout moment.

Les différentes choses que vous pouvez faire sont sous le lien ci-dessus. Ou, comme 95% des autres personnes, utilisez Implicit Wait implicite et Explicit Wait + ExpectedConditions si nécessaire.

Par exemple. après un clic, un élément de la page devrait devenir visible et vous devez attendre:

WebDriverWait wait = new WebDriverWait(driver, 10);  // you can reuse this one

WebElement elem = driver.findElement(By.id("myInvisibleElement"));
elem.click();
wait.until(ExpectedConditions.visibilityOf(elem));
33
Petr Janeček

Vous pouvez définir une variable JavaScript dans votre WepPage qui sera définie une fois chargée. Vous pouvez le placer n'importe où, mais si vous utilisez jQuery, $(document).onReady n'est pas un mauvais endroit pour commencer. Sinon, vous pouvez le mettre dans une balise <script> au bas de la page.

L'avantage de cette méthode par rapport à la vérification de la visibilité des éléments est que vous connaissez l'état exact de la page après l'exécution de l'instruction wait.

MyWebPage.html

... All my page content ...
<script> window.TestReady = true; </script></body></html>

Et dans votre test (exemple en C #):

// The timespan determines how long to wait for any 'condition' to return a value
// If it is exceeded an exception is thrown.
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5.0));

// Set the 'condition' as an anonymous function returning a boolean
wait.Until<Boolean>(delegate(IWebDriver d)
{
    // Check if our global variable is initialized by running a little JS
    return (Boolean)((IJavaScriptExecutor)d).ExecuteScript("return typeof(window.TestReady) !== 'undefined' && window.TestReady === true");
});
3
jmathew

Simple ready2use snippet, fonctionne parfaitement pour moi

static void waitForPageLoad(WebDriver wdriver) {
    WebDriverWait wait = new WebDriverWait(wdriver, 60);

    Predicate<WebDriver> pageLoaded = new Predicate<WebDriver>() {

        @Override
        public boolean apply(WebDriver input) {
            return ((JavascriptExecutor) input).executeScript("return document.readyState").equals("complete");
        }

    };
    wait.until(pageLoaded);
}
2
NarendraC

Je sais que ce post est vieux. Mais après avoir rassemblé tout le code ci-dessus, j'ai mis au point une méthode (solution) agréable pour gérer les pages courantes et les pages courantes. Le code est conçu uniquement pour C # (puisque Selenium est sans aucun doute le meilleur choix pour C # Visual Studio après une année de déconnages).

La méthode est utilisée comme méthode d'extension, ce qui signifie simplement. que vous pouvez ajouter plus de fonctionnalités (méthodes) dans ce cas, à l'objet IWebDriver. L'important est que vous deviez définir: 'this' dans les paramètres pour pouvoir l'utiliser. 

La variable de délai d'attente est la durée en secondes pendant laquelle le WebDriver attend, si la page ne répond pas. En utilisant les espaces de noms 'Selenium' et 'Selenium.Support.UI', il est possible d'exécuter une partie de javascript qui renvoie un booléen, que le document soit prêt (complet) et que jQuery est chargé. Si la page n'a pas jQuery, la méthode lève une exception. Cette exception est "interceptée" par le traitement des erreurs. Dans l'état catch, le document ne sera vérifié que pour son état prêt, sans vérification de jQuery.

public static void WaitUntilDocumentIsReady(this IWebDriver driver, int timeoutInSeconds) {
    var javaScriptExecutor = driver as IJavaScriptExecutor;
    var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));

    try {
        Func<IWebDriver, bool> readyCondition = webDriver => (bool)javaScriptExecutor.ExecuteScript("return (document.readyState == 'complete' && jQuery.active == 0)");
        wait.Until(readyCondition);
    } catch(InvalidOperationException) {
        wait.Until(wd => javaScriptExecutor.ExecuteScript("return document.readyState").ToString() == "complete");
    }
}
1
Bedirhan

Voici comment je le corrigerais, en utilisant un extrait de code pour vous donner une idée de base:

public class IFrame1 extends LoadableComponent<IFrame1> {

    private RemoteWebDriver driver;

    @FindBy(id = "iFrame1TextFieldTestInputControlID" ) public WebElement iFrame1TextFieldInput;
    @FindBy(id = "iFrame1TextFieldTestProcessButtonID" ) public WebElement copyButton;

    public IFrame1( RemoteWebDriver drv ) {
        super();
        this.driver = drv;
        this.driver.switchTo().defaultContent();
        waitTimer(1, 1000);
        this.driver.switchTo().frame("BodyFrame1");
        LOGGER.info("IFrame1 constructor...");
    }

    @Override
    protected void isLoaded() throws Error {        
        LOGGER.info("IFrame1.isLoaded()...");
        PageFactory.initElements( driver, this );
        try {
            assertTrue( "Page visible title is not yet available.", 
                    driver.findElementByCssSelector("body form#webDriverUnitiFrame1TestFormID h1")
                    .getText().equals("iFrame1 Test") );
        } catch ( NoSuchElementException e) {
            LOGGER.info("No such element." );
            assertTrue("No such element.", false);
        }
    }

    /**
     * Method: load
     * Overidden method from the LoadableComponent class.
     * @return  void
     * @throws  null
     */
    @Override
    protected void load() {
        LOGGER.info("IFrame1.load()...");
        Wait<WebDriver> wait = new FluentWait<WebDriver>( driver )
                .withTimeout(30, TimeUnit.SECONDS)
                .pollingEvery(5, TimeUnit.SECONDS)
                .ignoring( NoSuchElementException.class ) 
                .ignoring( StaleElementReferenceException.class ) ;
        wait.until( ExpectedConditions.presenceOfElementLocated( 
                By.cssSelector("body form#webDriverUnitiFrame1TestFormID h1") ) );
    }
....
0
djangofan

Récemment, lorsque je travaillais avec une application/RIA AJAX, je rencontrais le même problème! Et j'ai utilisé l'attente implicite, avec un temps d'environ 90 secondes. Il attend que l'élément soit disponible ... Nous pouvons donc nous assurer que la page est complètement chargée,

ajoutez une instruction booléenne, en vérifiant si la condition (une partie particulière de l'élément), est présente et assignez-la à une variable, recherchez la condition et uniquement si elle est vraie, "effectuez les actions nécessaires!" ... Dans De cette façon, j'ai compris, les deux attentes pourraient être utilisées ...

Ex: 

@Before

{ implicit wait statement}

@Test

{

boolean tr1=Driver.findElement(By.xpath("xx")).isEnabled/isDisplayed;

if (tr1==true && ____)//as many conditions, to make sure, the page is loaded

{

//do the necessary set of actions...
driver.findElement(By.xpath("yy")).click();

}

}

J'espère que cela t'aides!! C'est en phase de mise en œuvre, pour moi aussi ...

0
Mannii88

Ci-dessous, quelques codes de ma classe BasePageObject pour les attentes:

public void waitForPageLoadAndTitleContains(int timeout, String pageTitle) {
    WebDriverWait wait = new WebDriverWait(driver, timeout, 1000);
    wait.until(ExpectedConditions.titleContains(pageTitle));
}

public void waitForElementPresence(By locator, int seconds) {
    WebDriverWait wait = new WebDriverWait(driver, seconds);
    wait.until(ExpectedConditions.presenceOfElementLocated(locator));
}

public void jsWaitForPageToLoad(int timeOutInSeconds) {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    String jsCommand = "return document.readyState";

    // Validate readyState before doing any waits
    if (js.executeScript(jsCommand).toString().equals("complete")) {
        return;
    }

    for (int i = 0; i < timeOutInSeconds; i++) {
        TimeManager.waitInSeconds(3);
        if (js.executeScript(jsCommand).toString().equals("complete")) {
            break;
        }
    }
}

   /**
     * Looks for a visible OR invisible element via the provided locator for up
     * to maxWaitTime. Returns as soon as the element is found.
     *
     * @param byLocator
     * @param maxWaitTime - In seconds
     * @return
     *
     */
    public WebElement findElementThatIsPresent(final By byLocator, int maxWaitTime) {
        if (driver == null) {
            nullDriverNullPointerExeption();
        }
        FluentWait<WebDriver> wait = new FluentWait<>(driver).withTimeout(maxWaitTime, Java.util.concurrent.TimeUnit.SECONDS)
                .pollingEvery(200, Java.util.concurrent.TimeUnit.MILLISECONDS);

        try {
            return wait.until((WebDriver webDriver) -> {
                List<WebElement> elems = driver.findElements(byLocator);
                if (elems.size() > 0) {
                    return elems.get(0);
                } else {
                    return null;
                }
            });
        } catch (Exception e) {
            return null;
        }
    }

Méthodes de soutien:

     /**
     * Gets locator.
     *
     * @param fieldName
     * @return
     */
    public By getBy(String fieldName) {
        try {
            return new Annotations(this.getClass().getDeclaredField(fieldName)).buildBy();
        } catch (NoSuchFieldException e) {
            return null;
        }
    }
0
Mykola

Vous pouvez prendre une capture d'écran et enregistrer la page rendue dans un emplacement et vous pouvez vérifier la capture d'écran si la page est chargée complètement sans images brisées.

0