Firefox plugin: Test Automation Password Manager

I’ve recently come across a problem when doing UI testing with Firefox on a Mac against a web app that uses NTLM authentication. Every time I navigated to the web app I was presented with a dialog box asking me for my username and password.

I did some reading and came across Alister Scott’s Automatic Firefox authentication when using Selenium-WebDriver with AutoAuth post. In it he explains a way to get around the problem:

- Create a Firefox profile using the profile manager
- Add the required credentials to the profile
- Use the above Firefox profile when running tests
- Add the AutoAuth plugin to the profile at test execution time

The above would get around my problem, but it would lead to having to maintain a firefox profile which isn’t nice. So, I decided to attempt writing a firefox plugin that would allow me to add credentials to firefox’s password manager at runtime using Javascript. After all, according to the documentation it looked possible…

After a bit of hacking, the result is my first Firefox plugin: the Test Automation Password Manager plugin. It’s quite simple to use; you can find instructions here:

https://github.com/natritmeyer/test_automation_firefox_password_manager

…and the plugin page here:

https://addons.mozilla.org/en-US/firefox/addon/test-automation-password-ma/

I’ve not tested it extensively – “It Works On My Machine:)

How to show all cookies for a page

It’s not always that you can test a website from the comfort of Firefox + Firebug + FireCookie. When you have to use another browser where checking cookies isn’t so much fun (er… that’s all of them but firefox), you can at least get a dump of them to an alert box by putting the following into the address bar once the page has loaded:

javascript:alert(document.cookie.split(';').join('\n'))

Bookmark it to make life easier!

Lessons from a watir success story

There aren’t enough UI test automation success stories documented on the net, so here’s my contribution.

This post is about  how we started with zero automated UI testing capability, and how a couple of months later we had the capability to run 1,000 tests in 20 minutes (you may also notice some gorilla-style chest-beating). Not only that, our test execution results were always spot on (no false passes, no false fails), and our framework was easy to maintain and extend. Here’s how we did it and the lessons we learned along the way.

The Phoenix rises from the ashes…

After several false starts with UI testing (involving QTP and watin and fitnesse and and and…), it finally got off the ground after I demonstrated what could be achieved with watir. This was the first lesson for me: demonstrating working code makes for a far better case than “just believe me, I’ve done it before, it’ll work fine”. Realizing this, I spent a weekend putting together a simple ruby/test::unit/watir testing framework.

When, on monday morning, I demoed a bunch of working tests that could run over and over and over and each time give the correct results to a room full of doubters, it was decided that we’d give ruby/test::unit/watir a go.

An important constraint

In order to avoid the biggest mistake made in previous attempts at UI automation, I insisted on agreement to a very important constraint: the ruby/test::unit/watir framework would only test the web app part of the system. One of my philosophies when it comes to UI automation is: “use the right tool for the right job”. There would be no scope creep. The framework would be used for the web app only. The WPF fat client could be tested with something else – anything else, just please don’t subvert ruby/test::unit/watir for testing anything else but the web app.

This was all part of expectations management; over the years I’ve learned that this is one of the most important things when doing automated UI testing. It’s worth a separate post – I’ll get around to it.

Framework overview

The framework I came up with that weekend was very simple (and very unoriginal – I’ve done similar stuff before): each page in the app would be represented by a ruby module. Each “page module” would contain one method per control on the web page; the method when called would return the required object. Eg:

module HomePage
  def home_page_sign_in_link
    @browser.link(:xpath, "//a[contains(@href,'signin')]")
  end
  def home_join_button
    @browser.button(:id, "join")
  end
end

My experience is that IDs on objects often can’t be trusted. What I’ve found is that they usually get put in during development and that they are removed when they’re not required. If I write my object recognition code to depend on an ID I usually regret it. I’ve learned that xpath is often more reliable – IDs tend to disappear. Where I have reliable IDs, I’ll use them. But for anything else, I use xpath. I find myself maintaining ID-based object recognition a lot more than xpath-based object recognition. Your mileage may vary.

Each of these page modules was “mixed in” to a common module which was then mixed into the test, making each object in the system available to the test without having to deal with namespacing. Not the prettiest solution, but it got us working very quickly. We surprised ourselves by having no method name clashes – mainly due to the object naming convention we used.

Our app uses restful services so the net::http libraries were great. The calls were wrapped up in classes and placed alongside our test-data-generation code (random strings, valid usernames, etc). We wrote them to be independent of the rest of the framework (apart from the central config file that pointed them at the right environment) so that we could use them whenever and however we liked. This philosophy was applied to as much of the framework as possible – to the greatest extent possible we kept everything independent and modular. This allowed us to keep up with sweeping changes in the app we were testing. We had a lot of sweeping changes; to many people’s amazement (not least our own!) we were able to keep up with everything thrown at us.

One of watir’s greatest features which doesn’t get nearly enough air time is the “checkers” functionality. Every time a page is visited you can run custom code you’ve wrapped up in a ruby proc. Environment instability usually manifests itself in obvious ways. Watir checkers allow you to recognize these as soon as they appear. If, in your checker code, you raise an exception with a fixed message, you can find these when the test is done and mark the tests as “failed due to environment instability”; or you can be more specific, e.g: “failed due to database connection going down, again”. This saves us hours of work every day. Literally, hours.

Our test execution script keeps note of tests that failed. When all the tests have been run, the tests that failed get run again in the hope that environment instability “got better”. We’d have to rerun those tests manually at the end of a run anyway, so why not automate it? A big time saver.

Test::Unit

We used test::unit for executing the tests. It’s simplicity and rock-solid nature made it a good choice to start the framework with. It is also easily expanded/monkey-patched – we added a few things to it.

Though I have ruby experience, everyone else on the team had a C#/NUnit background; test::unit helped bridge their knowledge gap. Conceptually, test::unit and NUnit are identical (both are xunit tools) – the similarity meant one less thing for the others to learn. When under pressure, that was a good thing.

Netbeans as an IDE

Netbeansintegration with test::unit is great, so we decided on using it for our IDE. It turns out that NetBeans is a great IDE for watir testing; I heartily recommend it. The green ticks and red crosses were comforting to all the right people, the ease of viewing the source code of the watir/firewatir libraries was great, its intellisense wasn’t as bad as I was expecting it to be and its svn integration is better than anything else I’ve used so far. It’s also free so I didn’t have to get approval to buy it! It has loads of useful plugins too.

Firefox plugins

We used firefox (and therefore firewatir) because we needed to spoof useragents and headers – using firefox profiles meant we could test the mobile, browser and fat client webstores. Using firefox meant we could use plugins; here are the ones we found most useful:

  • Firebug – it is awesome. Install it, learn it, love it.
  • XPath Checker – It’s a great tool which does one thing very well: Write an xpath and it’ll show you what it evaluates to. There are other tools that do the same thing and more but the experience of everyone on the team was that xpath viewer was all they needed. Everything else was bloat.

Version Control

One area where testing is usually decades behind development is in the use of version control. This is probably due to the fact that most commercial tools make it less than trivial to do (the QTP and RFT test file formats are hardly version-control-friendly).

One of the many joys of using watir for UI testing is that using version control is simple – there are no ‘project files’ to worry about, no accompanying files that you need to check in when you change a test file, no bizarre links across directories, no weird inter-file dependancies.

Using version control for our tests and framework meant that we were free to change stuff as we saw fit – if something didn’t work we could just revert. I can’t recommend using version control enough. The “blame” feature in svn was particularly useful ;)

Parallelization of test execution

We got our super-fast execution time by cheating: we parallelized the execution of the tests. We used a Mac Pro (16GB RAM, 8 core, 4xHDD), the Parallels virtualization software to run 12 VMs, and a shonky “n mod 12″ function to decide what tests to run on each VM (we tried to get testjour working but it needs a fair bit more dev and documentation before it works as advertised and becomes usable).

One advantage of using a Mac (apart from its rock-solid stability) was “Exposé” – we could see all 12 VMs running at once. The amount of people who walked past our desk and got hypnotized by seeing 12 tiny PCs each executing as if they were self aware… – good PR for our team!

Results sanitization

It doesn’t matter if you can run a million tests in 5 minutes, if the results aren’t accurate and sanitized quickly. We’re quite proud of the fact that we provide our results within 5 minutes of finishing the last test (usually straight away). We’ve put a lot of effort into being able to do this and it’s one of the biggest selling points of the framework we’ve written. Here’s what we’ve done to get to this stage:

  1. Though we use many VMs to execute tests on, when execution is finished we write all the results to a central location. We don’t have to worry about collating results, it’s done automatically.
  2. We use the watir checker feature heavily (see above). Any test that failed because of an environment problem is marked as such. This means that we don’t need to investigate why the test failed – we know that it didn’t get past the login screen because we saw the “database connection down” message, not because there’s a bug in login.
  3. Where we find a bug, we put the number in the relevant assertion message. If the test fails at the same point in the next run, it’s because the bug is still there. The bug will be printed to the results file and when our summary script runs over the results it’ll mark the test as a known fail due to the bug referenced in the assertion message. A particularly awesome feature!
  4. Every test that hasn’t been marked as a known fail (environment or known bug) gets added to a list of tests that need to be investigated. They’ve already been run twice (see above), so there’s a very high chance that a regression bug has crept in.
  5. As well as a count of the various flavors of failed tests, we also gave percentages. These mean far more to the scrum masters, so that’s what we gave them.

Making the effort public

Initially, there was a lot of hostility toward the project – understandably! UI testing doesn’t have a good history where I work at the moment. One of the scrum masters pointed out that the best PR was fast, consistent and accurate test results and he was right. But there are a few more things that gave people reason to change their opinion.

  1. Every time our tests found a regression bug, we updated our “bug count” on a big, visible-to-all white board. There was no denying the value that we provided (we crossed the 100 bug count in only a few weeks)
  2. We gave the scrum masters remote access to our run machine. This allowed them to kick off test runs and watch them as they progressed. The instant feedback they got blew them away. The Exposé functionality let them see environment instability issues as soon as they occurred allowing them to go and kick some heads in the infrastructure team as soon as there was a problem.
  3. We put our test execution box on the end of our desk, facing out. As mentioned above, the Exposé function was great PR for the team. In the weeks before go-live, many evenings were spent huddled around the screen as we would do test run after test run with 6 or 7 people from varying levels of management all hypnotized by the tiny windows!
  4. The test owners wrote their tests on a wiki page – as soon as a test was automated we would mark it as such. Test owners knew exactly where they stood.

Summary of the lessons we learned

  1. Sell the idea of watir-based automated UI testing with working code
  2. Manage your managers’ expectations well
  3. Keep the framework simple – complexity you don’t need introduces risk you probably can’t afford
  4. Use the right tool for the right job
  5. Use free tools where possible; you’ll be freed from the hassle of purchasing stuff
  6. Use version control – it will be your salvation many times over
  7. For object-recognition, use xpath unless you have reliable IDs you can depend on
  8. Attempt to recognize environment-related errors in the test and report on them as such (watir checkers)
  9. Keep as much of your framework code as modular and independent as possible
  10. Make the test team’s work public. Provide test results as soon as is possible.
  11. Put a lot of effort into making results sanitization as quick as possible. There is very little as frustrating for a scrum master/test manager as knowing that test execution is complete but that the results “aren’t ready yet”.

That’s all for now!

Watir’s @browser.url returning the previous page’s url

I’ve come across a page which, when I navigate to it and ask it for it’s url (using @browser.url) gives me the previous page’s url. Very frustrating. To get around this, you can use direct DOM manipulation. Here’s a call you can use in place of @browser.url which will give you the actual url of the page:

my_current_url = @browser.js_eval("document.location.toString();")

The js_eval call takes a javascript command and returns any result. In this case, we ask the document (the root element of the document object model) and ask it for its location as a string. The javascript is evaluated, and the current url in the browser is returned. BTW, if you look at the firewatir code, the js_eval method is at the core of firewatir – it’s what passes commands to jssh and gets the results back.

Kill process by name using Ruby on Windows

Though it is possible in ruby to kill a process by its ID in ruby, it isn’t possible to kill processes by name, I guess because it would work differently across operating systems. This is a pain when using watir/firewatir, because the @browser.close method isn’t particularly reliable; making test runs flakey unless this problem is dealt with.

Process killing needs to be implemented for each platform; you can find out how to kill firefox using ruby on the mac here. The windows version of that is what this post is about.

`taskkill /im Firefox.exe /f /t >nul 2>&1`

Explanation: The above is the line of code you need to kill firefox. Taskkill is an exe that comes as standard on windows which is a little-known way of killing processes (back when I spent most of my time doing UI test automation in java (using RFT), I wrapped PSKill.exe to do the same thing). The /im option is the ‘image’ name (ie: the process name); the /f option tells taskkill to force quite the process, and the /t option performs a ‘tree kill’, ie: kill all child processes as well as the process specified. The whole taskkill command is piped to >nul 2>&1 which means that any output (standard or error) will disappear into a void – doing this means that your test output won’t be filled with useless info. Finally, the whole command is wrapped in ‘backticks’ (`, not single quotes!) which ruby interprets as a command to be executed by the OS, passing any results back to ruby.

Exception class/object expected (TypeError) on starting FireWatir

If you get the following…

/Library/Ruby/Gems/1.8/gems/firewatir-1.6.2/lib/firewatir/firefox.rb:1078:in `raise': exception class/object expected (TypeError)
from /Library/Ruby/Gems/1.8/gems/firewatir-1.6.2/lib/firewatir/firefox.rb:1078:in `js_eval'
from /Library/Ruby/Gems/1.8/gems/firewatir-1.6.2/lib/firewatir/firefox.rb:195:in `get_window_number'
from /Library/Ruby/Gems/1.8/gems/firewatir-1.6.2/lib/firewatir/firefox.rb:162:in `initialize'
from /Library/Ruby/Gems/1.8/gems/firewatir-1.6.2/lib/firewatir/firefox.rb:177:in `new'
from /Library/Ruby/Gems/1.8/gems/firewatir-1.6.2/lib/firewatir/firefox.rb:177:in `start'

…the problem is that firefox is already running, probably with a dialog box open. Be sure to close firefox before starting it. The problem is related to this one too…

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!