39
votes

I am using Selenium 2.20 WebDriver to create and manage a firefox browser with C#. To visit a page, i use the following code, setting the driver timeouts before visiting the 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

The problem is that sometimes pages take forever to load, and it appears that the default timeout for a page to load using the selenium WebDriver is 30 seconds, which is too long. And i don't believe the timeouts i am setting apply to the loading of a page using the GoToUrl() method.

So I am trying to figure out how to set a timeout for a page to load, however, i cannot find any property or method that actually works. The default 30 second timeout also seems to apply to when i click an element.

Is there a way to set the page load timeout to a specific value so that when i call the GoToUrl() method it will only wait my specified time before continuing?

9
Are you sure GoToUrl() waits for the page to load? My experience is that it doesn't. But that's just a feeling, not a fact.Torbjörn Kalin
yes, i am 100% sure that calling GoToUrl() blocks execution until the page is completely done loading, and i have measured a default timeout of 30 seconds for calling this method, after 30 seconds execution will continue, and i'm trying to reduce that default timeout of 30 seconds somehow.KabanaSoft
i have posted similar question: stackoverflow.com/questions/11958701/…Nick Kahn
@TorbjörnKalin It does block until the page loads as far as the onReady event is thrown by the browser. If theres post js and ajax ... that "page loaded" knowlege doesn't mean anything.AnthonyJClink

9 Answers

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

Note: driver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(5)) is now deprecated.

32
votes

In case this helps anyone still looking for the answer to this, the C# WebDriver API now contains the appropriate method.

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

With this you should be able to declare a wait explicitly.

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

you could also change the implicit wait time

driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));

I think that is the syntax in C#. (not to sure)

In ruby it is

@driver.manage.timeouts.implicit_wait = 30
@wait = Selenium::WebDriver::Wait.new(:timeout => 30)
4
votes

i found the solution this this issue. When creating a new FirefoxDriver, there are overloads in the constructor that allow you to specify a command timeout which is the maximum time to wait for each command, and it seems to be working when calling the GoToUrl() method:

driver = new FirefoxDriver(new FirefoxBinary(), profile, new TimeSpan(0, 0, 0, timeoutSeconds));

link to FirefoxDriver constructor documentation for reference: http://selenium.googlecode.com/svn/trunk/docs/api/dotnet/html/M_OpenQA_Selenium_Firefox_FirefoxDriver__ctor_2.htm

Hope this helps someone else who runs into this problem.

2
votes

As of 2018: Besides these:

driver.Manage().Timeouts().ImplicitWait.Add(System.TimeSpan.FromSeconds(5));      
driver.Manage().Timeouts().PageLoad.Add(System.TimeSpan.FromSeconds(5));
driver.Manage().Timeouts().AsynchronousJavaScript.Add(timespan));

wait for searching for an item, loading a page, and waiting for script respectively. There is:

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

We brazilians have a word for crappy workarounds "Gambiarra"... Well... at least they do the job... Here is mine:

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

What my WaitElement(By, int) does:

/// <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; }
}

After this, you can play with timeout...

Make By the things you notice that loads last in the page (like javascript elements and captchas) remembering: it will start working the // rest of your application before the page fully loads, therefore may be nice to put a Thread.Sleep(1000) at the end just to be sure...

Also notice that this method will be called AFTER the 60 seconds standard timeout from Selenium's DRIVER.Navigate().GoToUrl(url);

Not the best, but... as I said: A good gambiarra gets the job done...

1
votes

Page load timeouts are not implemented in the .NET bindings yet. Hopefully they will be soon.

1
votes

For anyone who wants the opposite effect: setting timeout longer than 60s.

You need both use:

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

and

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

The new FirefoxDriver(binary, profile, timeSpan) has been obsolete.

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

does not work.

This works. Use a property setter syntax.

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