If you are a tester that’s charged with automating the execution of a web application, there’s a fairly good chance that you won’t be using some of the cost solutions out there like QTP or SilkTest. There’s a better than even chance that you’ll be looking at open source testing solutions. If this is your first experience with such technologies, you might find it a bit daunting. Oftentimes the one thing you won’t find is a nice concise script that will at least give you a start. Complicating this is many blogs seem to indicate various tools all interconnect in some ways, or can only be used in certain contexts, leaving you to figure out a lot of the details yourself.
For me, when I look at these tools I need to know, as quickly as possible, if (1) they work at all and (2) if I can wrap my head around how to get started in the first place. Sometimes you just need a gentle nudge in the right direction to see how the technology works. When I practice with technologies, I create little “spike” files that do just enough to show me what I need to know. Here I’ll be showing you my spikes.
I’m going to be focusing on using the following technologies: RSpec, Watir, Selenium, Capybara, and WebDriver. These tools will help you test a user interface through a browser. You will hear these tools most often mentioned in the context of a Rails-specific application but here I’m going to be assuming that you’re not using the Rails platform. Given the number of tools I’ll be looking at, I trust it’s obvious this won’t be an in-depth look at each tool, nor even a tutorial for how to use them. Think of this as a tutorial for how to get started using them. While I’m by no means a language bigot, I am becoming a strong proponent of Ruby-based solutions. So what I’m going to be showing you here is Ruby code. However, this is not a tutorial for Ruby coding; rather I’m just going to show how to drive some of the technologies with Ruby code.
Given that the solutions are Ruby-based, this means you will need Ruby and Rubygems installed on your system. The problem is that how to do this differs among operating systems and on whether or not you are using something like Ruby Version Manager (on Linux-based systems) or pik (on Windows-based systems). There are plenty of resources out there (including the Ruby site itself) that tell you how to get everything installed. I would recommend going to one of those and getting yourself set up. Once you do that, make sure you have run the following commands to get the appropriate gems:
$ gem install rspec $ gem install watir-webdriver $ gem install selenium-webdriver $ gem install capybara
One question that you may be asking, as a tester, is whether you would always use all these technologies together. Probably not. WebDriver is a way to drive the execution of a browser and Selenium and Watir are two different test frameworks that can drive a browser. Which one you use is largely irrelevant, at least when starting out. Capybara is designed to wrap different drivers (like selenium-webdriver) under a common interface. RSpec is a bit different in that it’s a Domain Specific Language (DSL) for describing the expected behavior of an application with executable logic placed in between specific code constructs. The executable logic will be written in Selenium, Watir, Capybara, etc.
First, I wanted to take a look at watir-webdriver. There is actually just a Watir framework that doesn’t rely on WebDriver at all. So why use WebDriver? Well, most people will point you to Introducing WebDriver. Basically WebDriver is a relatively clean API that is not tied to any particular testing framework, which is why you have a watir-webdriver and a selenium-webdriver, for example. Put another way, different testing frameworks (Watir, Selenium) can use the same API (WebDriver) which theoretically broadens your options.
So let’s start with using watir-webdriver. What I did is create a file called spike_watir.rb and put the following Ruby code in it. (Note: If you’re not used to Ruby, I recommend typing the examples rather than just pasting them. This trains the hands and the mind together.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
require 'watir-webdriver' browser = Watir::Browser.new :firefox browser.goto("http://www.amazon.com") browser.text_field(:name, 'field-keywords').set("star wars") browser.button(:class, "nav-submit-input").click testResult = browser.text.match(/Showing .* of .* Results/) if testResult != nil puts "Result: #{testResult}" puts "PASS: Results Count verified." else puts "FAIL: Results Count not verified." end |
To execute this script, use the following command::
$ ruby spike_watir.rb
Okay, that seemed to work. I then did a quick compare of Selenium. I created a file called spike_selenium.rb and put the following Ruby code in it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
require 'selenium-webdriver' driver = Selenium::WebDriver.for :firefox driver.get "http://www.amazon.com" driver.find_element(:name => "field-keywords").send_keys("star wars") driver.find_element(:xpath => "//input[@class='nav-submit-input']").click testResult = driver.find_element(:tag_name => "body").text.match(/Showing .* of .* Results/) if testResult != nil puts "Result: #{testResult}" puts "PASS: Results Count verified." else puts "FAIL: Results Count not verified." end |
Again, to execute the script, use the following command:
$ ruby spike_selenium.rb
You’ll notice that the Watir and Selenium versions are pretty much the same in terms of approach although there are some differences in implementation. Many testers I’ve worked with often say they like the Watir approach since it tends to be more readable, but they also say that Selenium seems to have more attraction in their workplace. Personally, I go back and forth depending upon which framework is frustrating me the most at the moment. Right now I tend to prefer Watir over Selenium, mainly because I find myself jumping through less hoops. Your mileage will definitely vary.
With those initial spikes under my belt, I decided to try out Capybara. This one proved to be a little more involved. I created a file called spike_capybara.rb and put the following Ruby code in it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
require 'rspec' require 'capybara' require 'capybara/dsl' include Capybara::DSL include RSpec::Matchers Capybara.default_driver = :selenium Capybara.app_host = "http://www.amazon.com" visit "" fill_in('field-keywords', :with => "star wars") page.find(:xpath, "//input[@class='nav-submit-input']").click begin testResult = page.html.should match(/Showing .* of .* Results/) rescue puts "FAIL: Results Count not verified." end puts "Result: #{testResult.to_s}" puts "PASS: Results Count verified." |
Once again, to execute the script, use the following command:
$ ruby spike_capybara.rb
There’s a lot going on there but at least it executed in the way I expected and I could get a feel for how Capybara worked. This also introduced me to RSpec a bit more since I had to include it in order to get the same level of functionality that I had with the Watir and Selenium scripts.
With that accomplished, I initially liked Watir as my solution and thus I used that spike to continue with further research. As one example of that, I now wanted to use RSpec since my environment was trying to practice Behavior Driven Development (BDD) and RSpec is said to be a “BDD tool.” Along with using RSpect, I decided that I wanted to make this spike a little more complicated than my first one. Not only would this get me comfortable with Watir but it would also exercise some of the strengths of RSpec better. So I created a file called spike_spec_watir.rb and put the following Ruby code in it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
require 'rspec' require 'watir-webdriver' browser = Watir::Browser.new :firefox browser.goto("http://www.amazon.com") describe "Searching for items" do it "searches in all departments" do browser.text_field(:name, 'field-keywords').set("star wars") browser.button(:class, "nav-submit-input").click browser.text.match(/Showing .* of .* Results/) end it "performs a related search" do browser.link(:text, "star wars lego").click browser.text.match(/Showing .* of .* Results/) browser.text.match(/LEGO Star Wars (.*) by LEGO/) end it "searches in a specific department" do browser.select_list(:id, "searchDropdownBox").select("Books") browser.text_field(:name, 'field-keywords').set("star wars") browser.button(:alt, "Go").click browser.text.match(/Showing .* of .* Results/) browser.text.match("Paperback") end end |
To execute this script, use the following command:
$ rspec spike_spec_watir.rb
This is how you run any such file that uses RSpec to wrap the execution of your test logic. Now, obviously, it took me a little bit of legwork to figure out how all this worked so I could put it together. That legwork is often valuable. On the other hand, there’s also value when someone just gives you a clear way to start your own investigations. So treat the above code as that: a starting point that you can actually get started with, without (hopefully!) having to figure out a series of implementation details.
This convinced me that I could use RSpec and watir-webdriver to drive a web site. I realized that I could use the exact same structure for selenium-webdriver and/or my Capybara scripts. (I’ll leave that as an exercise for the reader.)
What I’m hoping this does is get you started playing with each one of these technologies and seeing how they work together as well as showing you that they aren’t terribly difficult to get started with, assuming you have a gentle nudge that shows you how things work. Sometimes just knowing that things are possible and having some simple examples that show you how is worth more than reams of explanation.
I recommend studying the above examples to see their commonalities as well as their differences. Eventually I’m going to have some posts that talk about using these technologies as part of a framework for your automated testing.
As a final note, these technologies change all the time and one of the dangers of writing about them is that what worked at one point may no longer work. So in the interests making it clear under what context the above spikes worked, I’ll note that I used the following gem versions:
- rspec (2.6.0)
- watir-webdriver (0.2.5)
- selenium-webdriver (0.2.2)
- capybara (1.0.0)
All of the Ruby logic was executed under Ruby version 1.9.2p180.
Excellent information in this post! I am currently using Watir and really like it. My boss is leaning towards selenium with Java. So now I need to learn Selenium. This article has given me a great starting point. Thanks so much!
Yeah, I have to say that I much prefer Watir myself. If you haven’t seen it yet, check out: http://watirmelon.com/. There’s a small project there called Watir-Page-Helper. (Or just check out https://github.com/alisterscott/watir-page-helper.) There’s a lot of good stuff on that site, including this: http://watirmelon.com/2011/05/05/selenium-webdriver-vs-watir-webdriver-in-ruby/.
If you want a framework that allows you to use both Selenium and Watir (along with Cucumber), check out https://github.com/cheezy/page-object. All of this is in Ruby, rather than Java. I’ve tried a lot of this in Java but the main problem for me is that it’s often quite a bit easier to do this stuff in Ruby. Granted, that’s a total subjective opinion but I’ve just found some of the Java infrastructure to be a bit clumsy when what I really need is a language that gets out of my way and let’s me do some cool things without a lot of overhead.
Another thing to look at might be Capybara, if you’re shopping around. It uses Selenium behind the scenes but provides an abstraction layer on top of it.
Thanks for the head start! It definitely helps to have some examples when learning a set of new tools. I can relate with the frustration of having to sort out so many different tools all used within different contexts!
The spike file idea is also very handy to use when learning these new tools. Much easier to take things one step at a time.
P.S.:
It looks like amazon.com changed their website, so some of the selectors no longer work. I was able to fix things by replacing
:alt, "Go"
with:class, "nav-submit-input"
, (and//div[@id='navGoButton']/input
with//input[@class='nav-submit-input']
)Indeed, James, you are correct. Amazon did change a few things on me. Thanks for bringing it to my attention. I have updated the post accordingly.
Awesome tutorial! Just love it.
You have written great “getting started to get intermediate automation tester” tutorial.
Thanks a ton!
Thank you for this! Very helpful.