Selenium Webdriver / C# - 点击后如何确认页面加载?

时间:2014-07-28 14:52:08

标签: c# selenium

我试图调用的网站基本上使用.ascx和aspx页面来呈现他们的项目。并且为了导航,您必须使用click事件而不是goto url。目前我正在使用Thread.Sleep(3000),但那很笨,我认为这不是最好的方法。

您可以添加什么以确保页面已从点击事件加载?

IWebElement myLink;

myLink = driver.FindElement(By.Id("ctl00_ctl00_cphContentArea_cphContentArea_ucwaag_lnkbtnDate" + i.ToString()));
myLink.Click();
Thread.Sleep(5000); //yeah need to fix this

3 个答案:

答案 0 :(得分:0)

我不确定是否这种方法,但我正在使用等待javascript变量设置的池化机制,当页面完全加载时手动设置(因为没有办法告诉它何时实际完成)。

C#

public void WaitUntilLoaded()
    {
        Func<IWebDriver, bool> test = drv =>
        {
          result = (bool?)js.ExecuteScript("return SeleniumHelper.isPageLoaded;");
        };

        TestHelper.WaitUntil(this.Driver, d => { }, test, Constants.Pause.Medium, "load", logWaitTime: true);
    }

internal static class TestHelper
   {
   private static readonly string StartDateString = DateTime.Now.ToString("yyyy-MM-ddTHH-mm-ss");
   private static readonly Random Rnd = new Random((int)DateTime.Now.Ticks);

   public static void WaitUntil(IWebDriver driver, Action<IWebDriver> action, Func<IWebDriver, bool> predicate, TimeSpan timeOut, string waitingForDescription, bool logWaitTime = false)
   {
       action(driver);

       int retryCount = 0;
       var now = DateTime.Now;
       var wait = new WebDriverWait(driver, timeOut);
       Func<IWebDriver, bool> fullPredicate = drv =>
       {
           var res = predicate(drv);
           if (!res)
               {
               bool hasErr = IsShowingErrorLoadingPage(drv);
               if (hasErr)
               {
                   Console.WriteLine(string.Format("Page is marked with [{0}]", "Error Loading Page"));
                   if (retryCount++ == 0)
                   {
                        Console.WriteLine("Retrying...");
                        action(driver);
                        res = false;
                   }
                }
            }

            return res;
        };

        try
        {
            wait.Until(fullPredicate);
        }
        catch (TimeoutException)
        {
            string waitMsg = timeOut.TotalSeconds >= 1 ? (timeOut.TotalSeconds + "s") : (timeOut.TotalMilliseconds + "ms");
            throw new TimeoutException(string.Format("Waited for {0} to {1} without success [{2}].", waitMsg, waitingForDescription, WritePageSource(driver)));
        }

        if (logWaitTime)
        {
            Console.WriteLine("WaitUntil: Requested wait: " + Math.Round(timeOut.TotalSeconds, 2).ToString("0.00").PadLeft(5, ' ') + "s; actual wait: " + Math.Round(DateTime.Now.Subtract(now).TotalSeconds, 3).ToString("0.000").PadLeft(6, ' ') + "s");
        }
  }

 public static bool IsStale(IWebElement element)
 {
     return Throws<StaleElementReferenceException>(() => element.GetAttribute("x"));
 }

 public static bool IsShowingErrorLoadingPage(IWebDriver driver)
 {
        IWebElement failedToLoad;
        try
        {
            failedToLoad = driver.FindElements(By.TagName("h1")).Where(el => el.Text == "Error Loading Page").FirstOrDefault();
        }
        catch (StaleElementReferenceException)
        {
            failedToLoad = null;
        }

        return failedToLoad != null;
    }
}

使用Javascript:

 function SeleniumHelper() {
    isPageLoaded = false;
    this.markPageAsLoaded = function () {
        logger.log('page marked as loaded');
        isPageLoaded = true;
    };

}

答案 1 :(得分:0)

最好等待目标页面上的已知元素出现 - 引入任何睡眠语句会使您的测试变得非常脆弱,因此您应该尽量避免这种情况。

这样的事情:

wait.Until(d => d.FindElement(By.Id(someId)));

在这种情况下,您可能会发现此Stackoverflow question很有用。

答案 2 :(得分:0)

这是我们在尝试使用Selenium时遇到的完全相同的问题。

我们通过使用等待条件解决了这个问题。

wait.Until(ExpectedConditions.ElementExists(locator));
wait.Until(ExpectedConditions.ElementIsVisible(locator));

我们必须同时使用ElementExists和ElementIsVisible来解决控件在页面上但不可见的问题