Selenium С# Webdriver: Подождите, пока не появится элемент

Я хочу убедиться, что элемент присутствует до того, как webdriver начинает делать вещи.

Я пытаюсь заставить что-то вроде этого работать:

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

Я в основном пытаюсь настроить любую важную функцию.

Ответ 1

В качестве альтернативы вы можете использовать неявное ожидание:

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

Неявное ожидание - сообщить WebDriver о опросе DOM для определенного количество времени, когда вы пытаетесь найти элемент или элементы, если они не сразу доступны. Значение по умолчанию равно 0. После установки неявное ожидание задается для жизни экземпляра объекта WebDriver.

Ответ 2

Использование решения, предоставленного Майком Кваном, может оказать влияние на общую производительность тестирования, поскольку неявное ожидание будет использоваться во всех вызовах FindElement. Много раз вам нужно, чтобы FindElement автоматически сбой, когда элемент отсутствует (вы тестируете неверную страницу, отсутствующие элементы и т.д.). При неявном ожидании эти операции будут ждать истечения всего таймаута, прежде чем выбросить исключение. Неявное ожидание по умолчанию установлено на 0 секунд.

Я написал небольшой метод расширения для IWebDriver, который добавляет параметр ожидания (в секундах) к методу FindElement(). Это совершенно понятно:

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

Я не кэшировал объект WebDriverWait, так как его создание очень дешево, это расширение может использоваться одновременно для разных объектов WebDriver, и я только делаю оптимизации, когда это необходимо.

Использование прямолинейно:

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();

Ответ 3

Вы также можете использовать

ExpectedConditions.ElementExists

Итак, вы будете искать доступность элемента, подобного этому

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

Источник

Ответ 4

Здесь вариант решения @Loudenvier, который также работает для получения нескольких элементов:

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

Ответ 5

Вдохновленный решением Loudenvier, здесь используется метод расширения, который работает для всех объектов ISearchContext, а не только IWebDriver, который является специализацией первого. Этот метод также поддерживает ожидание до отображения элемента.

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

Пример использования:

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();

Ответ 6

Я запутал любую функцию с предикатом. Heres немного вспомогательный метод:

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

Ответ 7

Вы можете узнать что-то подобное на С#.

Это то, что я использовал в JUnit - Selenium

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

Импортировать связанные пакеты

Ответ 8

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

Ответ 9

Команда clickAndWait не преобразуется при выборе формата Webdriver в Selenium IDE. Вот обходной путь. Добавьте строку ожидания ниже. Реально, проблема заключалась в щелчке или событии, которое произошло до этой одной строки 1 в моем коде С#. Но на самом деле, просто убедитесь, что у вас есть WaitForElement перед любым действием, в котором вы ссылаетесь на объект "By".

HTML-код:

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

Код С#/NUnit:

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

Ответ 10

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'))

от EC вы также можете выбрать другие условия попробуйте следующее: http://selenium-python.readthedocs.org/api.html#module-selenium.webdriver.support.expected_conditions

Ответ 11

public bool doesWebElementExist(string linkexist)
{
     try
     {
        driver.FindElement(By.XPath(linkexist));
        return true;
     }
     catch (NoSuchElementException e)
     {
        return false;
     }
}

Ответ 12

Попробуйте этот код:

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

Ответ 13

Явная ожидаемая

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

Пример:

wait.until(ExpectedConditions.visibilityOfElementLocated(UiprofileCre.UiaddChangeUserLink));

Ответ 14

Вы не хотите ждать слишком долго, прежде чем элемент изменится. В этом коде веб-драйвер ждет до 2 секунд, прежде чем продолжить.

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromMilliseconds(2000));
wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.Name("html-name")));

Ответ 15

Поскольку я разделяю определения элементов страницы и сценарии тестирования страницы, используя уже найденный IWebElement для наглядности, это можно сделать так:

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

Ответ 16

Я вижу несколько уже опубликованных решений, которые отлично работают! Однако на всякий случай кому-то нужно что-то еще, я подумал, что отправлю два решения, которые я лично использовал в селене С#, чтобы проверить, присутствует ли элемент! Надеюсь, это поможет, ура!

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

}

Вот второй

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

}

Ответ 17

Использовал Rn222 и Aknuds1 для использования ISearchContext, который возвращает либо отдельный элемент, либо список. И минимальное количество элементов может быть указано:

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

}

Пример использования:

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();

Ответ 18

Это повторно используемая функция для ожидания присутствия элемента в DOM с использованием явного ожидания.

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

Ответ 19

Мы можем достичь этого следующим образом:

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

Ответ 20

WebDriverWait не вступит в силу.

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

Это сразу вызовет исключение, когда страница станет "интерактивной". Я не знаю почему, но тайм-аут действует так, как будто его не существует.

Возможно, SeleniumExtras.WaitHelpers работает, но я не пробовал. Это официально, но было разделено на другой пакет nuget. Вы можете сослаться на С# Selenium & # 39; Ожидаемые условия устарели & # 39;.

Сам использую FindElements и проверим, используется ли Count == 0, если true, await Task.Delay. Это действительно не совсем эффективно.

Ответ 21

Был поиск, как ждать в Selenium для условия, приземлился в этой теме, и вот что я сейчас использую:

    WebDriverWait wait = new WebDriverWait(m_driver, TimeSpan.FromSeconds(10));
    wait.Until(d => ReadCell(row, col) != "");

ReadCell(row, col) != "" может быть любым условием. Так вот так:

  • это моя
  • позволяет встраивать

Ответ 22

 new WebDriverWait(driver, TimeSpan.FromSeconds(10)).
   Until(ExpectedConditions.PresenceOfAllElementsLocatedBy((By.Id("toast-container"))));

Ответ 23

Первый ответ хорош, моя проблема заключалась в том, что необработанные исключения не правильно закрывали веб-драйвер, и он сохранял то же самое первое значение, которое я использовал, которое составляло 1 секунду.

Если вы получите ту же проблему

restart you visual studio и убедитесь, что all the exceptions are handled правильно.