Selenium WebDriver - 如何使用C#设置页面加载超时时间

43

我正在使用 Selenium 2.20 WebDriver 和 C# 创建和管理 Firefox 浏览器。为了访问一个页面,我使用以下代码,在访问 URL 之前设置驱动程序的超时时间:

driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(5)); // Set implicit wait timeouts to 5 secs
driver.Manage().Timeouts().SetScriptTimeout(new TimeSpan(0, 0, 0, 5));  // Set script timeouts to 5 secs
driver.Navigate().GoToUrl(myUrl);   // Goto page url

问题在于有时页面加载需要很长时间,而使用selenium WebDriver加载页面的默认超时时间为30秒,这太长了。我不相信所设置的超时时间适用于使用GoToUrl()方法加载页面。

因此,我正在尝试找出如何设置页面加载超时时间,但我找不到任何实际起作用的属性或方法。默认的30秒超时时间似乎也适用于当我单击元素时。

是否有一种方法可以将页面加载超时时间设置为特定值,以便在调用GoToUrl()方法时只等待指定的时间然后继续执行?


你确定 GoToUrl() 会等待页面加载完成吗?我的经验是它并不会。但这只是一种感觉,而非事实。 - Torbjörn Kalin
是的,我可以百分之百确定调用GoToUrl()会阻塞执行,直到页面完全加载完成,而我已经测量了调用此方法的默认超时时间为30秒,30秒后执行将继续进行,我正在尝试以某种方式减少这个默认的30秒超时时间。 - KabanaSoft
我已经发布了类似的问题:https://dev59.com/dGfWa4cB1Zd3GeqPfUbA - Nick Kahn
@TorbjörnKalin 当页面触发onReady事件时,它会阻塞直到页面加载完成。如果存在post js和ajax,则“页面已加载”信息没有任何意义。 - AnthonyJClink
9个回答

47
driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(5);

注意:现在driver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(5))已被弃用。


你知道默认值是什么吗? - tedi

32

如果还有人在寻找答案,C# WebDriver API现在包含了适当的方法。

driver.Manage().Timeouts().SetPageLoadTimeout(timespan)

3
我只希望有人能清楚地描述页面加载超时与隐式等待的区别。什么情况下页面加载完成但元素没有加载? - JasonCoder
9
从C#智能感知中可以看出,ImplicitlyWait是在页面上搜索元素的时间,SetPageLoadTimeout是等待URL加载的时间,而SetScriptTimeout是等待异步JS加载的时间。 - jpvantuyl

6

通过这个,您应该能够明确地声明等待。

WebDriverWait wait = new WebDriverWait(browser, new TimeSpan(time in seconds));
wait.until(Your condition)

你可以更改隐式等待时间。
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));

我认为这是C#中的语法。(不太确定)
在Ruby中,它是:
@driver.manage.timeouts.implicit_wait = 30
@wait = Selenium::WebDriver::Wait.new(:timeout => 30)

1
这不会起作用,因为GoToUrl()方法会阻止执行,因此在该方法完成或超时之前,我无法执行任何代码,默认情况下似乎是30秒。感谢回复。 - KabanaSoft
2
所以你需要更改你的隐式等待时间 - driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(5)); 将5秒减少到任何你想要的时间。这将影响你在gotourl上的等待时间。 - Amey
1
你也可以尝试使用wait.until (driver.Navigate().GoToUrl(myUrl)); // 跳转到页面URL,在这里你明确定义了等待执行gotoURL命令的时间。 - Amey
1
@seleniumnewbie: 我不知道为什么wait.until(driver.Navigate().GoToUrl(myUrl)); // 跳转到页面url会有点赞,但是从我的结果来看这根本不起作用。 - Shane

4
我已经找到了解决这个问题的方法。在创建新的FirefoxDriver时,构造函数中有多个重载可以让你指定命令超时时间,这是等待每个命令的最长时间,当调用GoToUrl()方法时似乎是有效的:
driver = new FirefoxDriver(new FirefoxBinary(), profile, new TimeSpan(0, 0, 0, timeoutSeconds));

以下是FirefoxDriver构造函数文档的链接,供参考: http://selenium.googlecode.com/svn/trunk/docs/api/dotnet/html/M_OpenQA_Selenium_Firefox_FirefoxDriver__ctor_2.htm

希望这能帮助遇到这个问题的其他人。


我已经发布了类似的问题:https://dev59.com/dGfWa4cB1Zd3GeqPfUbA - Nick Kahn

3

我们巴西人有一个词来形容糟糕的解决办法,“Gambiarra”... 好吧... 至少这些方法能够完成工作... 这是我的经验:

var url = "www.your.url.here"
try {
    DRIVER.Navigate().GoToUrl(url);
} catch {
    // Here you can freely use the Selenium's By class:
    WaitElement(By.Id("element_id_or_class_or_whatever_to_be_waited"), 60);
}
// rest of your application

我这个WaitElement(By, int)函数的作用:

/// <summary>
/// Waits until an element of the type <paramref name="element"/> to show in the screen.
/// </summary>
/// <param name="element">Element to be waited for.</param>
/// <param name="timeout">How long (in seconds) it should be waited for.</param>
/// <returns>
/// False: Never found the element. 
/// True: Element found.
/// </returns>
private bool WaitElement(By element, int timeout)
{
    try {
        Console.WriteLine($" - Waiting for the element {element.ToString()}");
        int timesToWait = timeout * 4; // Times to wait for 1/4 of a second.
        int waitedTimes = 0; // Times waited.
        // This setup timesout at 7 seconds. you can change the code to pass the 

        do {
            waitedTimes++;
            if (waitedTimes >= timesToWait) {
                Console.WriteLine($" -- Element not found within (" +
                $"{(timesToWait * 0.25)} seconds). Canceling section...");
                return false;
            }
            Thread.Sleep(250);
        } while (!ExistsElement(element));

        Console.WriteLine($" -- Element found. Continuing...");
    //  Thread.Sleep(1000); // may apply here
        return true;
    } catch { throw; }
}

在此之后,您可以使用timeout进行测试...。
将加载在页面中最后的事物(如JavaScript元素和验证码)制作为By注意事项。请记住:它会在页面完全加载之前开始运行// rest of your application,因此可能很好在结尾处放置 Thread.Sleep(1000),以确保...。
还要注意,此方法将在Selenium的DRIVER.Navigate().GoToUrl(url);标准超时60秒后调用。
这不是最好的方法,但正如我所说:一个好的gambiarra可以完成工作...。

2
截至2018年: 除此之外:
driver.Manage().Timeouts().ImplicitWait.Add(System.TimeSpan.FromSeconds(5));      
driver.Manage().Timeouts().PageLoad.Add(System.TimeSpan.FromSeconds(5));
driver.Manage().Timeouts().AsynchronousJavaScript.Add(timespan));

等待搜索项目、加载页面和等待脚本的时间。

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));

2

目前,.NET绑定还没有实现页面加载超时。希望它们能够尽快实现。


这个问题有任何更新吗?经过9年,似乎它们仍未被实现。我的系统在10秒后仍会超时,无论我在ImplicitWait、AsynchronousJavaScript或PageLoad上设置了多长的超时时间。 - John Chesshir

1

对于希望产生相反效果的人:将超时设置为长于60秒。

你需要同时使用:

new FirefoxDriver(FirefoxDriverService.CreateDefaultService(), new FirefoxOptions(), TimeSpan.FromSeconds(120))

并且

driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(120);

"

new FirefoxDriver(binary, profile, timeSpan) 已经过时。

"

0
driver.Manage().Timeouts().SetPageLoadTimeout(timespan) 

不起作用。

这个可以工作。使用属性设置器语法。

driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(15);

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