Tuesday, July 27, 2010

Watir timeout : handle browser hang/stuck while loading isuue with watir in IE

Watir: 1.4.1
Ruby: 1.8.6

I used to get frequent conditions wherein when my watir script is running and the browser would hang indefinitely and load painfully slowly when changing links using goto, when navigating to another page, when submitting a form...

The timeout functionality as supplied in  http://watirmelon.com/2009/03/26/timing-out-watir-with-timeouttimeout/ which was a great resource for this article and the base for it.

My custom code to check if the page is loaded and if not, redo the action:
browser_loaded=0
while (browser_loaded == 0)
begin
 browser_loaded=1
 Timeout::timeout(10) do
  browser.goto(“http://mysite.com”) # goto or click a link
 end
 rescue Timeout::Error => e
  puts “Page load timed out: #{e}”
  browser_loaded=0
  retry
 end
end

This works fantastic, only problem is that when there are many pages to load, this entire code has to be inserted which substantially increases the code writeup.

To counter this, I decided to make a function and call this block anytime I have to jump to a page.

So now whenever I have any submit action or page load during which a browser hang is expected, I call it using the following.
sureLoadLink(30){browser.goto("http://mysite/")} 

Note that '30' used here is the timeout. The part inside the curly braces above is the one that I am executing with failproof execution.

Here is the called function. yield is the place where the called block code is substituted.
def sureLoadLink(mytimeout) 
 browser_loaded=0
 while (browser_loaded == 0)
   begin
   browser_loaded=1
   Timeout::timeout(mytimeout)  do
    yield
   end
   rescue Timeout::Error => e
    puts "Page load timed out: #{e}"
    browser_loaded=0
    retry
   end
 end
end

This worked great for page changed and navigation clicks.

However, when submitting forms and IE hanging with indefinite loading time when the form is being submitted, this had an issue. My problematic code which submitted a form looked like this...
#go to form
browser.text_field(:id,'discussion_subject').value="Subject"
browser.text_field(:id,'discussion_post').value="Post"
sureLoadLink(30){ browser.button(:id, 'createbutton').click }

The problem was that Watir would fill the form and prepare it for being submitted, but when the submission failed due to IE loading getting stuck, the sureLoadLink function would try to resubmit it. This would fail and throw a object not found error as no the page has moved on partially and the button is gone out of the scan area for Watir!

In order to handle this, I used the concept of a transaction. Redoing every action required to make a commit. Thus making sure that if submission failed, all required steps are repeated leading to form submit and not only the form submit action itself. This worked and the code snippet looked like this:
sureLoadLink(30){
 #go to form
 browser.text_field(:id,'discussion_subject').value="Subject"
 browser.text_field(:id,'discussion_post').value="Post"
 browser.button(:id, 'createbutton').click 
}

Thus managed to solve all issues! yay...

A final piece of working code would look like this:

sureLoadLink(30){
 #browser.goto("http://mysite")
 browser.text_field(:id,'content').value="Comment 10"
 browser.form(:id, "comment_form").submit
}


def sureLoadLink(mytimeout)
 browser_loaded=0
 while (browser_loaded == 0)
 begin
  browser_loaded=1
  Timeout::timeout(mytimeout)  do
   yield
  end
  rescue Timeout::Error => e
   puts "Page load timed out: #{e}"
   browser_loaded=0
   retry
  end
 end
end

I would also suggest the following as it made my timeout errors far less frequent.
  1. Upgrade your watir and ruby installation to the latest version (Watir 1.6.5).
  2. Download and update IE 8 with the latest updates.
~joviano_dias@hotmail.com

1 comment:

  1. I think we dont need browser_loaded and while loop if we use retry

    ReplyDelete