首页 文章

Selenium c#Webdriver:等到元素存在

提问于
浏览
149

我想确保在webdriver开始执行操作之前存在一个元素 .

我正试图让这样的东西起作用:

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

我主要是在努力设置如何设置任何功能..

20 回答

  • 16

    你可以在C#中找到类似的东西 .

    这就是我在JUnit中使用的 - Selenium

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

    做导入相关的包

  • 2

    在Selenium IDE中选择Webdriver格式时,不会转换clickAndWait命令 . 这是解决方法 . 添加下面的等待行 . 实际上,问题是在我的C#代码中的第1行之前发生的点击或事件 . 但实际上,只需确保在引用“By”对象的任何操作之前有WaitForElement .

    HTML code:

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

    或者,您可以使用隐式等待:

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

    隐式等待是指在尝试查找一个或多个元素(如果它们不是立即可用)时,将WebDriver轮询DOM一段时间 . 默认设置为0.设置后,将为WebDriver对象实例的生命周期设置隐式等待 .

  • 1

    Using the solution provided by Mike Kwan may have an impact in overall testing performance, since the implicit wait will be used in all FindElement calls. 很多时候你会对格式错误的页面,缺少元素等进行重新测试 . 使用隐式等待,这些操作将在抛出异常之前等待整个超时到期 . 默认隐式等待设置为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();
    
  • -1

    你也可以使用

    ExpectedConditions.ElementExists

    因此,您将搜索这样的元素可用性

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

    Source

  • 237

    这是@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);
        }
    }
    
  • 9

    受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();
    
  • 3

    我用谓词混淆了任何函数 . 下面是一个小帮手方法:

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

    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

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

    明确等待

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

    例:

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

    试试这段代码:

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

    您不希望在元素更改之前等待太久 . 在此代码中,webdriver在继续之前等待最多2秒 .

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

    由于我正在使用已经找到的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;
            }
        };
    }
    
  • -1

    我看到已发布的多个解决方案非常有用!但是,如果有人需要别的东西,我想我会发布两个我个人在selenium C#中使用的解决方案来测试一个元素是否存在!希望它有所帮助,欢呼!

    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; 
        }
    
    }
    
  • 0
    public bool doesWebElementExist(string linkexist)
    {
         try
         {
            driver.FindElement(By.XPath(linkexist));
            return true;
         }
         catch (NoSuchElementException e)
         {
            return false;
         }
    }
    
  • 0

    使用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.
    /// </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); } }

    Example usage:

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

    正在寻找如何在Selenium等待条件,登陆这个线程,这就是我现在使用的:

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

    ReadCell(row, col) != "" 可以是任何条件 . 喜欢这种方式因为:

    • 这是我的

    • 允许内联

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

    第一个答案是好的,我的问题是 unhandled exceptions didn't close web driver properly 并且它保持了我使用的第一个值,即1秒 .

    如果你遇到同样的问题

    restart you visual studio 并确保 all the exceptions are handled 正确 .

相关问题