如何在Selenium WebDriver中等待元素加载?

6

我是selenium webdriver的新手,正在测试一个应用程序。在我的应用程序中,我需要测试关联Facebook账户。每当我点击链接时,将显示弹出窗口,在那里我必须输入凭据。有时我能够成功关联,有时测试失败。我知道原因是因为它需要时间加载弹出窗口,而下一条命令被执行,因此无法找到元素。我已经使用了Thread.Sleep,但我想使用隐式等待或显式等待,这总是比Thread.Sleep更好的做法。如何使用隐式等待,并在哪里使用该命令?请给予建议。谢谢。

 public void SocialFaceBook()
    {           
        string currentWindow = driver.CurrentWindowHandle;
        PopupWindowFinder finder = new PopupWindowFinder(driver);
        string facebookWindow = finder.Click(driver.FindElement(By.XPath("//div[@id='panelFacebook']/div[2]/div[3]/div[3]/a")));
        // Switch To FaceBook Window
        driver.SwitchTo().Window(facebookWindow);
        System.Threading.Thread.Sleep(3000);

        // Link
        // Email Address
        IWebElement faceBookLinkEmail = driver.FindElement(By.Id("email"));
        faceBookLinkEmail.SendKeys(SocialFaceBookEmail);

        // Password
        IWebElement faceBookLinkPass = driver.FindElement(By.Id("pass"));
        faceBookLinkPass.SendKeys(SocialFaceBookPass);

        // Log In Button
        IWebElement faceBookLinkLogin = driver.FindElement(By.XPath("//input[@id='u_0_1']"));
        faceBookLinkLogin.Click();

        // Switch To Main Window
        driver.SwitchTo().Window(currentWindow);
        System.Threading.Thread.Sleep(3000);

        // Sync            
        IWebElement faceBookSync = driver.FindElement(By.XPath("//div[@id='panelFacebook']/div[2]/div[3]/div[2]/a"));
        faceBookSync.Click();

        // Unlink
        IWebElement faceBookUnLink = driver.FindElement(By.XPath("//div[@id='panelFacebook']/div[2]/div[3]/div[1]/a"));
        faceBookUnLink.Click();
    }

有时候弹出窗口加载不完全,导致找不到登陆信息;有时候因为脸书账号链接需要时间,所以无法找到同步按钮。请给予建议。

请参考以下链接获取更多信息:http://stackoverflow.com/questions/18063377/wait-for-an-element-using-selenium-webdriver 无论是隐式等待还是显式等待都可以使用。 - Mike Beeler
这里还提供了各种解决方案:https://dev59.com/c2w05IYBdhLWcg3w11W0。 - Codatrix
@user3931772 我成功地找到了一种方法,在等待某个元素可见之前点击它。感谢你提出这个问题! - tylerlindell
6个回答

19

WebDriverWait wait = new WebDriverWait(driver, 30); wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("locator")));

这段代码会等待元素被定位最长时间为30秒,如果在此之前找到该元素,它将执行...


谢谢你的回答!它帮助我找到了一个非常好的解决方案。我也在这里发布了我的解决方案。 - tylerlindell
谢谢,这对我很有帮助!我的第二行代码看起来像这样:wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.CssSelector("#dummy-div"))); - userlond
使用TimeSpan.FromSeconds(30)代替30。 - Setmax

4

我需要对@Vicky的答案进行一些小的修改,但这是我得到的一个可以调用的方法。

public static void WaitForElementLoad(By by, int timeoutInSeconds)
    {
        if (timeoutInSeconds > 0)
        {
            WebDriverWait wait = new WebDriverWait(webDriver, TimeSpan.FromSeconds(timeoutInSeconds));
            wait.Until(ExpectedConditions.ElementIsVisible(by));
        }
    }

我是这样调用它的:

MyClass.WaitForElementLoad(By.CssSelector("div#div1 div strong a"), 10);

0

我曾经编写了一个函数,每秒检测一个元素是否存在。如果找到则继续执行,否则抛出超时错误。但是在这个函数中,我仍然使用了Thread.Sleep。

期望有其他更好的解决方案。


Thread.Sleep不是一个好的实践方式,因为它会无论如何等待,即使元素被找到或未找到。我尝试使用隐式等待,但测试失败了。不知道原因,但它不起作用。 - user3931772

0

我使用ExpectedCondition.visibilityOf(element)代替线程休眠


0

隐式等待 - 最长等待时间以识别对象,每500毫秒将识别一次对象。如果在最长时间内无法识别对象,则会抛出nosuchelement异常。

显式等待 - 用于ajax页面加载以实现相同的目的。

最长等待时间与线程休眠相同。


0
编写了一个项目的方法:
public static void WaitForElementPresentBy(By by)
        {
            try
            {
                Wait.Until(ExpectedConditions.ElementIsVisible(by));
            }
            catch (TimeoutException te)
            {

                Assert.Fail("The element with selector {0} didn't appear. The exception was:\n {1}", by, te.ToString());
            }
        }

等待应该已经被定义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接