wake-up-neo.com

Selenium c # Webdriver: Warten, bis Element vorhanden ist

Ich möchte sicherstellen, dass ein Element vorhanden ist, bevor der Web-Treiber anfängt, Dinge zu tun. 

Ich versuche so etwas zum Laufen zu bringen: 

WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0,0,5));
wait.Until(By.Id("login"));

Ich habe vor allem Probleme, wie man die anomalen Funktionen einrichten kann.

154
AyKarsi

Alternativ können Sie implizites Warten verwenden:

driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);

Eine implizite Wartezeit ist, WebDriver anzuweisen, das DOM nach einem bestimmten .__ abzufragen. Zeit, wenn Sie versuchen, ein Element oder Elemente zu finden, wenn sie .__ sind. nicht sofort verfügbar Die Standardeinstellung ist 0. Nach der Einstellung wird der Das implizite Warten wird für die Lebensdauer der WebDriver-Objektinstanz festgelegt.

135
Mike Kwan

Die Verwendung der von Mike Kwan bereitgestellten Lösung kann sich auf die allgemeine Testleistung auswirken, da das implizite Warten in allen FindElement-Aufrufen verwendet wird. Oftmals soll das FindElement sofort fehlschlagen, wenn ein Element nicht vorhanden ist (Sie testen auf eine fehlerhafte Seite, fehlende Elemente usw.). Bei der impliziten Wartezeit würden diese Operationen warten, bis der gesamte Timeout abläuft, bevor die Ausnahme ausgelöst wird. Die standardmäßige implizite Wartezeit ist auf 0 Sekunden festgelegt.

Ich habe eine kleine Erweiterungsmethode für IWebDriver geschrieben, die der Methode FindElement () einen Timeout-Parameter (in Sekunden) hinzufügt. Es ist ziemlich selbsterklärend:

public static class WebDriverExtensions
{
    public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds)
    {
        if (timeoutInSeconds > 0)
        {
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
            return wait.Until(drv => drv.FindElement(by));
        }
        return driver.FindElement(by);
    }
}

Ich habe das WebDriverWait-Objekt nicht im Cache gespeichert, da seine Erstellung sehr billig ist. Diese Erweiterung kann gleichzeitig für verschiedene WebDriver-Objekte verwendet werden. Ich mache Optimierungen nur dann, wenn sie letztendlich benötigt werden. 

Die Verwendung ist unkompliziert:

var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://localhost/mypage");
var btn = driver.FindElement(By.CssSelector("#login_button"));
btn.Click();
var employeeLabel = driver.FindElement(By.CssSelector("#VCC_VSL"), 10);
Assert.AreEqual("Employee", employeeLabel.Text);
driver.Close();
245
Loudenvier

Sie können auch verwenden 

ExpectedConditions.ElementExists

Sie suchen also nach einer Elementverfügbarkeit

new WebDriverWait(driver, TimeSpan.FromSeconds(timeOut)).Until(ExpectedConditions.ElementExists((By.Id(login))));

Quelle

79
Zain Ali

Hier ist eine Variation der @ Loudenvier-Lösung, die auch mehrere Elemente abruft:

public static class WebDriverExtensions
{
    public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds)
    {
        if (timeoutInSeconds > 0)
        {
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
            return wait.Until(drv => drv.FindElement(by));
        }
        return driver.FindElement(by);
    }

    public static ReadOnlyCollection<IWebElement> FindElements(this IWebDriver driver, By by, int timeoutInSeconds)
    {
        if (timeoutInSeconds > 0)
        {
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
            return wait.Until(drv => (drv.FindElements(by).Count > 0) ? drv.FindElements(by) : null);
        }
        return driver.FindElements(by);
    }
}
27
Rn222

Inspiriert von Loudenviers Lösung ist hier eine Erweiterungsmethode, die für alle ISearchContext-Objekte geeignet ist, nicht nur für IWebDriver, eine Spezialisierung der ersteren. Diese Methode unterstützt auch das Warten, bis das Element angezeigt wird.

static class WebDriverExtensions
{
    /// <summary>
    /// Find an element, waiting until a timeout is reached if necessary.
    /// </summary>
    /// <param name="context">The search context.</param>
    /// <param name="by">Method to find elements.</param>
    /// <param name="timeout">How many seconds to wait.</param>
    /// <param name="displayed">Require the element to be displayed?</param>
    /// <returns>The found element.</returns>
    public static IWebElement FindElement(this ISearchContext context, By by, uint timeout, bool displayed=false)
    {
        var wait = new DefaultWait<ISearchContext>(context);
        wait.Timeout = TimeSpan.FromSeconds(timeout);
        wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
        return wait.Until(ctx => {
            var elem = ctx.FindElement(by);
            if (displayed && !elem.Displayed)
                return null;

            return elem;
        });
    }
}

Verwendungsbeispiel:

var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://localhost");
var main = driver.FindElement(By.Id("main"));
var btn = main.FindElement(By.Id("button"));
btn.Click();
var dialog = main.FindElement(By.Id("dialog"), 5, displayed: true);
Assert.AreEqual("My Dialog", dialog.Text);
driver.Close();
16
aknuds1

Ich verwechselte jede Funktion mit Prädikat. Heres eine kleine Hilfsmethode:

   WebDriverWait wait;
    private void waitForById(string id) 
    {
        if (wait == null)            
            wait = new WebDriverWait(driver, new TimeSpan(0,0,5));

        //wait.Until(driver);
        wait.Until(d => d.FindElement(By.Id(id)));
    }
9
AyKarsi

Sie können etwas in C # herausfinden. 

Das habe ich in JUnit-Selenium verwendet 

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

Importieren Sie verwandte Pakete 

3
Aditi

Python:

from Selenium import webdriver
from Selenium.webdriver.support import expected_conditions as EC
from Selenium.webdriver.support.ui import WebDriverWait
from Selenium.webdriver.common.by import By

driver.find_element_by_id('someId').click()

WebDriverWait(driver, timeout).until(EC.presence_of_element_located((By.ID, 'someAnotherId'))

von EC können Sie auch andere Bedingungen wählen Versuchen Sie Folgendes: http://Selenium-python.readthedocs.org/api.html#module-Selenium.webdriver.support.expected_conditions

//wait up to 5 seconds with no minimum for a UI element to be found
WebDriverWait wait = new WebDriverWait(_pagedriver, TimeSpan.FromSeconds(5));
IWebElement title = wait.Until<IWebElement>((d) =>
{
    return d.FindElement(By.ClassName("MainContentHeader"));
});
2
Brian121212

Der Befehl clickAndWait wird nicht konvertiert, wenn Sie das Web-Treiber-Format in der Selenium IDE auswählen. Hier ist die Problemumgehung. Fügen Sie die Wartezeile unten hinzu. Realistischerweise war das Problem der Klick oder das Ereignis, das vor diesem Einzeiligen Code 1 in meinem C # -Code stattfand. Stellen Sie jedoch sicher, dass Sie vor jeder Aktion, bei der Sie auf ein "By" -Objekt verweisen, über ein WaitForElement verfügen.

HTML Quelltext:

<a href="http://www.google.com">xxxxx</a>

C #/NUnit-Code:

driver.FindElement(By.LinkText("z")).Click;
driver.WaitForElement(By.LinkText("xxxxx"));
driver.FindElement(By.LinkText("xxxxx")).Click();
2
MacGyver

Da ich Seitenelementdefinitionen und Seitentestszenarien mit bereits gefundenem IWebElement für die Sichtbarkeit trenne, könnte dies folgendermaßen erfolgen:

public static void WaitForElementToBecomeVisibleWithinTimeout(IWebDriver driver, IWebElement element, int timeout)
{
    new WebDriverWait(driver, TimeSpan.FromSeconds(timeout)).Until(ElementIsVisible(element));
}

private static Func<IWebDriver, bool> ElementIsVisible(IWebElement element)
{
    return driver => {
        try
        {
            return element.Displayed;              
        }
        catch(Exception)
        {
            // If element is null, stale or if it cannot be located
            return false;
        }
    };
}
1
Angel D

Explizites Warten 

public static  WebDriverWait wait = new WebDriverWait(driver, 60);

Beispiel:

wait.until(ExpectedConditions.visibilityOfElementLocated(UiprofileCre.UiaddChangeUserLink));
1
Pavan T

Versuchen Sie diesen Code: 

 New WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(Function(d) d.FindElement(By.Id("controlName")).Displayed)
1

Sie möchten nicht zu lange warten, bevor sich das Element ändert. In diesem Code wartet der Web-Treiber bis zu 2 Sekunden, bevor er fortgesetzt wird.

WebDriverWait wait = new WebDriverWait (Treiber, TimeSpan.FromMilliseconds (2000)); 
 Wait.Until (ExpectedConditions.VisibilityOfAllElementsLocatedBy (By.Name ("html-name")); __.
1
user3607478
public bool doesWebElementExist(string linkexist)
{
     try
     {
        driver.FindElement(By.XPath(linkexist));
        return true;
     }
     catch (NoSuchElementException e)
     {
        return false;
     }
}
0
Madhu

Ich sehe bereits mehrere Lösungen, die gut funktionieren! Nur für den Fall, dass jemand etwas anderes benötigt, habe ich gedacht, ich würde zwei Lösungen posten, die ich persönlich in Selenium C # verwendet habe, um zu testen, ob ein Element vorhanden ist! Ich hoffe es hilft, Prost! 

public static class IsPresent
{
    public static bool isPresent(this IWebDriver driver, By bylocator)
    {

        bool variable = false;
        try
        {
            IWebElement element = driver.FindElement(bylocator);
            variable = element != null;
        }
       catch (NoSuchElementException){

       }
        return variable; 
    }

}

Hier ist der zweite 

    public static class IsPresent2
{
    public static bool isPresent2(this IWebDriver driver, By bylocator)
    {
        bool variable = true; 
        try
        {
            IWebElement element = driver.FindElement(bylocator);

        }
        catch (NoSuchElementException)
        {
            variable = false; 
        }
        return variable; 
    }

}
0
newITguy

Verwendet Rn222 und Aknuds1, um einen ISearchContext zu verwenden, der entweder ein einzelnes Element oder eine Liste zurückgibt. Eine Mindestanzahl von Elementen kann angegeben werden:

public static class SearchContextExtensions
{
    /// <summary>
    ///     Method that finds an element based on the search parameters within a specified timeout.
    /// </summary>
    /// <param name="context">The context where this is searched. Required for extension methods</param>
    /// <param name="by">The search parameters that are used to identify the element</param>
    /// <param name="timeOutInSeconds">The time that the tool should wait before throwing an exception</param>
    /// <returns> The first element found that matches the condition specified</returns>
    public static IWebElement FindElement(this ISearchContext context, By by, uint timeOutInSeconds)
    {
        if (timeOutInSeconds > 0)
        {
            var wait = new DefaultWait<ISearchContext>(context);
            wait.Timeout = TimeSpan.FromSeconds(timeOutInSeconds);
            return wait.Until<IWebElement>(ctx => ctx.FindElement(by));
        }
        return context.FindElement(by);
    }
    /// <summary>
    ///     Method that finds a list of elements based on the search parameters within a specified timeout.
    /// </summary>
    /// <param name="context">The context where this is searched. Required for extension methods</param>
    /// <param name="by">The search parameters that are used to identify the element</param>
    /// <param name="timeoutInSeconds">The time that the tool should wait before throwing an exception</param>
    /// <returns>A list of all the web elements that match the condition specified</returns>
    public static IReadOnlyCollection<IWebElement> FindElements(this ISearchContext context, By by, uint timeoutInSeconds)
    {

        if (timeoutInSeconds > 0)
        {
            var wait = new DefaultWait<ISearchContext>(context);
            wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
            return wait.Until<IReadOnlyCollection<IWebElement>>(ctx => ctx.FindElements(by));
        }
        return context.FindElements(by);
    }
    /// <summary>
    ///     Method that finds a list of elements with the minimum amount specified based on the search parameters within a specified timeout.<br/>
    /// </summary>
    /// <param name="context">The context where this is searched. Required for extension methods</param>
    /// <param name="by">The search parameters that are used to identify the element</param>
    /// <param name="timeoutInSeconds">The time that the tool should wait before throwing an exception</param>
    /// <param name="minNumberOfElements">
    ///     The minimum number of elements that should meet the criteria before returning the list <para/>
    ///     If this number is not met, an exception will be thrown and no elements will be returned
    ///     even if some did meet the criteria
    /// </param>
    /// <returns>A list of all the web elements that match the condition specified</returns>
    public static IReadOnlyCollection<IWebElement> FindElements(this ISearchContext context, By by, uint timeoutInSeconds, int minNumberOfElements)
    {
        var wait = new DefaultWait<ISearchContext>(context);
        if (timeoutInSeconds > 0)
        {
            wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
        }

        // Wait until the current context found the minimum number of elements. If not found after timeout, an exception is thrown
        wait.Until<bool>(ctx => ctx.FindElements(by).Count >= minNumberOfElements);

        //If the elements were successfuly found, just return the list
        return context.FindElements(by);
    }

}

Verwendungsbeispiel:

var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://localhost");
var main = driver.FindElement(By.Id("main"));
// It can be now used to wait when using elements to search
var btn = main.FindElement(By.Id("button"),10);
btn.Click();
//This will wait up to 10 seconds until a button is found
var button = driver.FindElement(By.TagName("button"),10)
//This will wait up to 10 seconds until a button is found, and return all the buttons found
var buttonList = driver.FindElements(By.TagName("button"),10)
//This will wait for 10 seconds until we find at least 5 buttons
var buttonsMin= driver.FindElements(By.TagName("button"), 10, 5);
driver.Close();
0
havan

WebDriverWait wird nicht wirksam.

var driver = new FirefoxDriver(
    new FirefoxOptions().PageLoadStrategy = PageLoadStrategy.Eager
);
driver.Navigate().GoToUrl("xxx");
new WebDriverWait(driver, TimeSpan.FromSeconds(60))
    .Until(d => d.FindElement(By.Id("xxx"))); // a tag that close to the end

Dies würde sofort eine Ausnahme auslösen, sobald die Seite "interaktiv" ist. Ich weiß nicht warum, aber das Timeout funktioniert so, als ob es nicht existiert.

Vielleicht funktioniert SeleniumExtras.WaitHelpers aber ich habe es nicht versucht. Es ist offiziell, wurde aber in ein anderes Nuget-Paket aufgeteilt. Sie können sich auf C # Selen 'ExpectedConditions is obsolet' beziehen .

Ich selbst verwende FindElements und überprüfe, ob Count == 0, wenn ja, verwende await Task.Delay. Es ist wirklich nicht sehr effizient.

0
imba-tjd

Das können wir so erreichen:

public static IWebElement WaitForObject(IWebDriver DriverObj, By by, int TimeOut = 30)
{
    try
    {
        WebDriverWait Wait1 = new WebDriverWait(DriverObj, TimeSpan.FromSeconds(TimeOut));
        var WaitS = Wait1.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.PresenceOfAllElementsLocatedBy(by));
        return WaitS[0];
    }
    catch (NoSuchElementException)
    {
        Reports.TestStep("Wait for Element(s) with xPath was failed in current context page.");
        throw;
    }
}
0
Krunal

This is the reusable function to wait for an element present in DOM using Explicit Wait. Public void WaitForElement(IWebElement element, int timeout = 2){ WebDriverWait wait = new WebDriverWait(webDriver, TimeSpan.FromMinutes(timeout)); wait.IgnoreExceptionTypes(typeof(NoSuchElementException)); wait.IgnoreExceptionTypes(typeof(StaleElementReferenceException)); wait.Until<bool> (driver => { try { return element.Displayed; } catch(Exception) { return false; } }); }

0
Balakrishna