Finding a form by xpath in Firewatir causes ‘Stack Level Too Deep’

If in a firewatir script you look for a form using xpath, you’ll get the following output:


SystemStackError: stack level too deep
from /Library/Ruby/Gems/1.8/gems/firewatir-1.6.2/lib/firewatir/htmlelements.rb:72:in `locate'
from /Library/Ruby/Gems/1.8/gems/firewatir-1.6.2/lib/firewatir/MozillaBaseElement.rb:1012:in `exists?'
from /Library/Ruby/Gems/1.8/gems/firewatir-1.6.2/lib/firewatir/MozillaBaseElement.rb:965:in `assert_exists'
from /Library/Ruby/Gems/1.8/gems/firewatir-1.6.2/lib/firewatir/MozillaBaseElement.rb:1403:in `method_missing'
from /Library/Ruby/Gems/1.8/gems/firewatir-1.6.2/lib/firewatir/htmlelements.rb:75:in `locate'
from /Library/Ruby/Gems/1.8/gems/firewatir-1.6.2/lib/firewatir/MozillaBaseElement.rb:1012:in `exists?'
from /Library/Ruby/Gems/1.8/gems/firewatir-1.6.2/lib/firewatir/MozillaBaseElement.rb:965:in `assert_exists'
from /Library/Ruby/Gems/1.8/gems/firewatir-1.6.2/lib/firewatir/MozillaBaseElement.rb:1403:in `method_missing'
... 4235 levels...

Known bug, apparently:

http://groups.google.com/group/watir-general/browse_thread/thread/8ef42aef5dae69df

Get around it by using :id or some other locator. Here’s some code to replicate the above:


require "FireWatir"
include FireWatir
@browser = Firefox.start("http://www.google.com")
@browser.form(:xpath, "//form").exists?

How to quit Firefox using FireWatir on a Mac

There seems to be a bug in the way that FireWatir on the mac quits firefox… it doesn’t! When you try, you end up with a dialog box saying:

Close Firefox
A copy of Firefox is already open. Only one copy of Firefox can be open at a time.

Here it is…

close_firefox

These dialog boxes pile up on top of each other during a test run; a few minutes into the run it looks like the dialog box is surrounded by a big black band!

To get around the problem and kill firefox reliably, you can use the following method. It simply calls the killall command line app and tells it to kill the firefox process. Here’s the method:


def kill_mac_firefox_browser
  `killall -9 firefox-bin`
end

Brutal but effective.

BTW, here’s how to kill a process by name using ruby on windows; the example used is how to kill firefox too!

How to know if you have a secure session in Watir

Sometimes you’re on a secure page, sometimes you’re not. How to know? There’s a very simple method you can write to find out, based on the browser’s current url. Here’s the method:


def is_session_secure?
  @browser.url =~ /^https/ ? true : false
end

It’s worth noting that the method highlights how much you can get done with very little code using ruby and watir. Here’s what it does: first, get the url out of the browser. Then, see if the url matches a simple regex. Since this operation is done in a ternary operation, a simple true/false will result. And, since ruby returns what the final line in a method resolves to, the true/false result of the match will be returned. Another nail in the coffin of big and bloated UI automation tools!

Here’s an example of the code in use…


require "rubygems"
require "firewatir"
require "test/unit"

include FireWatir

class GoogleSecurePageTests < Test::Unit::TestCase
  def setup
    @browser = Firefox.start("http://www.google.com")
  end

  def test_google_https
    assert(!is_session_secure?)
    @browser.link(:text, "Sign in").click
    assert(is_session_secure?)
  end

  def is_session_secure?
    @browser.url =~ /^https/ ? true : false
  end
end

How to get only direct child objects in Watir

When you come across methods in watir that return child objects for the first time (eg: the ‘lis‘ in @browser.ul(:id,’main’).lis ) you’d think they’d return only the direct child objects. Frustratingly, they don’t. They’ll also return nested objects of the same type. Here’s some example html:



<ul id='main'>
  <li></li>
  <li> </li>
  <li>
  <ul>
    <li></li>
  </ul>
  </li>
</ul>
  

If you call @browser.ul(:id, 'main').lis.length (to get the number of child li objects), you’d get the answer: 4. Intuitively, you’d expect to get the answer 3. Well, I would, and everyone else I’ve mentioned this to agrees [grumble grumble]. Now the example above is trivial – in the real world, nesting ul‘s in li‘s is common and can get quite complex. It gets even more complex when what you really want is to be able to type the following:


@browser.ul(:id,'main').lis[4].links[7]

…but instead you end up writing convoluted, complex, fragile and unmaintainable code to do what you’d think the above code should do – get the 7th link that is a direct child of the 4th li element that is a direct child of the ul.

But, there is a solution. Perversely, the solution is part of the watir/firewatir code. If you’re prepared to use xpath to identify your objects (my personal preference is to always use xpath), there’s a great method called elements_by_xpath which will do exactly what you want. Again, using the example above, you can get 3 as the answer (number of direct child li’s of the ul) with the following code:


@browser.elements_by_xpath("//ul[@id='main']/li").length

Even better, in doing the following:


my_lis = []
my_lis = @browser.elements_by_xpath("//ul[@id='main']/li")

…the my_lis variable will contain an array of elements; each element being of the right type – Li‘s in this instance. This works with links, table rows, table cells… everything! You can go back to writing clean, maintainable tests!

Note, this works in watir and firewatir. I haven’t checked safariwatir…

How to check for errors on every page using Watir

Testing a web app in an unstable environment is a pain. Many tests will fail for environmental reasons and filtering out those results can take a while. To make this sort of thing less painful, Watir and its derivatives (eg: firewatir) provide the ability to run any number of methods each time a page is loaded. They call these methods “checkers”… because… they check stuff. Here’s how to use them:

1) Write your checker
Checkers are Ruby Procs – essentially, nameless methods stored in variables. Here’s an example:


check_for_bad_things = Proc.new do
  puts "Server Error!" if @browser.text.include?("server error")
end

2) Add the checker to your instance of the browser


@browser = Watir::Browser.new
@browser.add_checker(check_for_bad_things)

3) Run your test. Every time a page is loaded, the check_for_bad_things proc is executed; and instead of seeing obscure failures when the test environment dies, you’ll see a message saying “Server Error!” making it easy to spot tests that failed for environmental/non-regression reasons.

You can make the checkers more useful by making them throw exceptions instead of just printing a line to the console. This way, they’ll cause tests to end with error instead of failed, making it even easier to sort out real failed tests from fails due to environment instability.

Fix for Firewatir visible? method

The visible? method in the ruby Firewatir 1.6.2 gem isn’t great. After some hunting around, I ended up here and found a working monkeypatch. Here’s the code:


class Element
  def visible?
    assert_exists
    jssh_command = "var val = 'true'; var str = ''; var obj = #{element_object}; while (obj != null) { try { str = document.defaultView.getComputedStyle(obj,null).visibility; if (str=='hidden') { val = 'false'; break; } str = #{DOCUMENT_VAR}.defaultView.getComputedStyle(obj,null).display; if (str=='none') { val = 'false'; break; } } catch(err) {} obj = obj.parentNode; } val;"
    jssh_socket.send("#{jssh_command}\n", 0)
    vals = read_socket()
    return (vals == 'false') ? false : true
  end
  public:visible?
end

Works for me!

The page I got this from says that the above will be in the next version of Firewatir… I hope so, because it doesn’t work without it!

Problem starting Watir: uninitialized constant Windows::API::Error (NameError) – Fixed!

I tried to run the example ‘GoogleTest.rb‘, and got the following error:

C:/Ruby/lib/ruby/gems/1.8/gems/windows-pr-0.9.3/lib/windows/thread.rb:59: uninitialized constant Windows::API::Error (NameError)
from C:/Ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from C:/Ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from C:/Ruby/lib/ruby/gems/1.8/gems/win32-process-0.5.9/lib/win32/process.rb:3
from C:/Ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from C:/Ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from C:/Ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-process.rb:1
from C:/Ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from C:/Ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from C:/Ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie.rb:45
from GoogleTest.rb:20

I trawled around for a while and came across a solution. If you get the problem above, the fix is quite simple: you need to get a later version of the ‘windows-pr’ gem. Here are the commands you need:

gem uninstall windows-pr (answer Yes to the question it asks)
gem install windows-pr

It installed version 1.0.6 – I was previously using 0.9.3, clearly not recent enough! Anyway, with that, the problem was fixed.

Running NetBeans ruby tests from the command line

As far as doing UI testing with watir/firewatir goes, NetBeans is a fantastic IDE. It’s lightweight, but powerful enough to do pretty much anything I need. The integration with Test::Unit is particularly good: I select a test file, I call “Run > Test File”, I wait, I see pretty green and red indicators for the tests. But what if I want to run the tests from the command line? The NetBeans project structure means that it isn’t a matter of simply running ruby all_my_tests.rb. I took a look at what NetBeans actually did when it runs the test files (using the magic of ps -ax), and I’ve managed to compress the whole thing into:

cd project_dir
ruby -I lib -I test test/all_my_tests.rb

That’s the mac/unix/linux syntax. The windows syntax is the same:

cd project_dir
ruby -I lib -I test test\all_my_tests.rb