Selenium c # Webdriver: дождитесь появления элемента - PullRequest
165 голосов
/ 09 августа 2011

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

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

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

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

Ответы [ 23 ]

254 голосов
/ 06 сентября 2011

Использование решения, предоставленного Майком Кваном, может повлиять на общую производительность тестирования, поскольку неявное ожидание будет использоваться во всех вызовах 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();
141 голосов
/ 09 августа 2011

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

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

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

80 голосов
/ 28 февраля 2013

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

ExpectedConditions.ElementExists

Таким образом, вы будете искать такие элементы доступности

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

Источник

29 голосов
/ 04 апреля 2012

Вот вариант решения @ 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);
    }
}
16 голосов
/ 08 ноября 2012

Вдохновленный решением 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();
9 голосов
/ 09 августа 2011

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

   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)));
    }
3 голосов
/ 08 августа 2012

Вы можете найти что-то подобное в C #.

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

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

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

2 голосов
/ 18 января 2012

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

HTML-код:

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

C # / NUnit код:

driver.FindElement(By.LinkText("z")).Click;
driver.WaitForElement(By.LinkText("xxxxx"));
driver.FindElement(By.LinkText("xxxxx")).Click();
2 голосов
/ 08 декабря 2011
//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 голосов
/ 16 апреля 2014

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...