Selenium2 with ruby

47163 ワード


Introduction
The Ruby bindings for Selenium/WebDriver are available as the  selenium-webdriver  gem. There are many other Selenium gems out there, but this is the only official, maintained gem. If you're looking for a slightly higher level API built on the same technology, you may want to check out  watir-webdriver .
The bindings support Ruby 1.8.7 through 1.9.2, JRuby and Rubinius.
API docs
Changelog
The gem also includes the older selenium-client gem for use with Selenium RC. When reading the docs, keep in mind that these two namespaces refer to different APIs:
Selenium::WebDriver - the WebDriver API
Selenium::Client - Selenium RC API (previously released as the selenium-client gem)
For people who are new to Selenium, we recommend starting directly with Selenium::WebDriver, and focusing on the two main classes,Selenium::WebDriver::Driver and Selenium::WebDriver::Element. This is the entry point to the whole WebDriver API.
The rest of this document deals with Selenium::WebDriver exclusively.
API Example
The bindings provide a slightly rubified version of the WebDriver API:
 
 
require "selenium-webdriver"

driver = Selenium::WebDriver.for :firefox
driver.navigate.to "http://google.com"

element = driver.find_element(:name, 'q')
element.send_keys "Hello WebDriver!"
element.submit

puts driver.title

driver.quit

 
 
Driver examples:
 
 
 
# execute arbitrary javascript
puts driver.execute_script("return window.location.pathname")

# wait for a specific element to show up
wait = Selenium::WebDriver::Wait.new(:timeout => 10) # seconds
wait.until { driver.find_element(:id => "foo") }

 
 
Element examples:
 
 
# get an attribute
class_name = element.attribute("class") 

# is the element visible on the page?
element.displayed?

# click the element
element.click

# get the element location
element.location

# scroll the element into view, then return its location
element.location_once_scrolled_into_view

# get the width and height of an element
element.size

# press space on an element - see Selenium::WebDriver::Keys for possible values
element.send_keys :space

# get the text of an element
element.text

 
 
Advanced user interactions (see  ActionBuilder ):
 
 
driver.action.key_down(:shift).
              click(element).
              double_click(second_element).
              key_up(:shift).
              drag_and_drop(element, third_element).
              perform
 
IE
Make sure that Internet Options → Security has the same Protected Mode setting (on or off, it doesn't matter as long as it is the same value) for all zones.
Chrome
Command line switches
For a list of switches, see  chrome_switches.cc :
 
 
driver = Selenium::WebDriver.for :chrome, :switches => 
%w[--ignore-certificate-errors --disable-popup-blocking --disable-translate]

 
 
Tweaking profile preferences
For a list of prefs, see  pref_names.cc .
 
 
profile = Selenium::WebDriver::Chrome::Profile.new
profile['download.prompt_for_download'] = false
profile['download.default_directory'] = "/path/to/dir"

driver = Selenium::WebDriver.for :chrome, :profile => profile

 
See also  ChromeDriver .
Remote
The  RemoteWebDriver  makes it easy to control a browser running on another machine. Download the jar (from  Downloads ) and launch the server:
java -jar selenium-server-standalone.jar
Then connect to it from Ruby
driver = Selenium::WebDriver.for(:remote)

By default, this connects to the server running on localhost:4444 and opens Firefox. To connect to another machine, use the :url option:
driver = Selenium::WebDriver.for(:remote, :url => "http://myserver:4444/wd/hub")

To launch another browser, use the :desired_capabilities option:
driver = Selenium::WebDriver.for(:remote, :desired_capabilities => :chrome)

You can also pass an instance of Selenium::WebDriver::Remote::Capabilities, e.g.:
include Selenium

caps = WebDriver::Remote::Capabilities.htmlunit(:javascript_enabled => true)
driver = WebDriver.for(:remote, :desired_capabilities => caps)

You may want to set the proxy settings of the remote browser (this currently only works for Firefox):
include Selenium

caps = WebDriver::Remote::Capabilities.firefox(:proxy => WebDriver::Proxy.new(:http => "myproxyaddress:8080"))
driver = WebDriver.for(:remote, :desired_capabilities => caps)

Or if you have a proxy in front of the remote server:
include Selenium

client = WebDriver::Remote::Http::Default.new
client.proxy = Proxy.new(:http => "proxy.org:8080")

driver = WebDriver.for(:remote, :http_client => client)

See  `Selenium::WebDriver::Proxy`  for more options.
For the remote Firefox driver you can configure the profile, see the section  Tweaking Firefox preferences .
Firefox
The  FirefoxDriver  lets you configure the profile used.
Adding an extension
It's often useful to have Firebug available in the Firefox instance launched by WebDriver:
include Selenium

profile = WebDriver::Firefox::Profile.new
profile.add_extension("/path/to/firebug.xpi")

driver = WebDriver.for :firefox, :profile => profile

Using an existing profile
You can use an existing profile as a template for the WebDriver profile by passing the profile name (see firefox -ProfileManager to set up custom profiles.)
driver = Selenium::WebDriver.for(:firefox, :profile => "my-existing-profile")

If you want to use your default profile, pass :profile => "default"
You can also get a Profile instance for an existing profile and tweak its preferences. This does not modify the existing profile, only the one used by WebDriver.
default_profile = Selenium::WebDriver::Firefox::Profile.from_name "default"
default_profile.native_events = true

driver = Selenium::WebDriver.for(:firefox, :profile => default_profile)

Tweaking Firefox preferences
Use a proxy:
profile = Selenium::WebDriver::Firefox::Profile.new
proxy = Selenium::WebDriver::Proxy.new(:http => "proxy.org:8080")
profile.proxy = proxy

driver = Selenium::WebDriver.for :firefox, :profile => profile

Automatically download files to a given folder:
profile = Selenium::WebDriver::Firefox::Profile.new
profile['browser.download.dir'] = "/tmp/webdriver-downloads"
profile['browser.download.folderList'] = 2
profile['browser.helperApps.neverAsk.saveToDisk'] = "application/pdf"

driver = Selenium::WebDriver.for :firefox, :profile => profile

If you are using the remote driver you can still configure the Firefox profile:
profile = Selenium::WebDriver::Firefox::Profile.new
profile['foo.bar'] = true
  
capabilities = Selenium::WebDriver::Remote::Capabilities.firefox(:firefox_profile => profile)
driver = Selenium::WebDriver.for :remote, :desired_capabilities => capabilities

For a list of possible preferences, see  this page .
Custom Firefox path
If your Firefox executable is in a non-standard location:
Selenium::WebDriver::Firefox.path = "/path/to/firefox"
driver = Selenium::WebDriver.for :firefox

Native events
Native events are enabled by default on Windows. To turn them off:
profile = Selenium::WebDriver::Firefox::Profile.new
profile.native_events = false

driver = Selenium::WebDriver.for(:firefox, :profile => profile)

Experimental support for native events is available on Linux. Set profile.native_events = true to turn this on.
Opera
The  OperaDriver  is always run as a  RemoteWebDriver  server which the Ruby bindings connect to.
To get started, first  download  the selenium-server-standalone jar and set the SELENIUM_SERVER_JAR environmental variable to point to its location:
export SELENIUM_SERVER_JAR=/path/to/server-standalone.jar
Then you can simply create a new instance of Selenium::WebDriver with the :opera option:
driver = Selenium::WebDriver.for :opera
driver.navigate.to 'http://opera.com/'

Timeouts
Implicit waits
WebDriver lets you configure implicit waits, so that a call to #find_element will wait for a specified amount of time before raising aNoSuchElementError:
  driver = Selenium::WebDriver.for :firefox
  driver.manage.timeouts.implicit_wait = 3 # seconds

Explicit waits
Use the Wait class to explicitly wait for some condition:
  wait = Selenium::WebDriver::Wait.new(:timeout => 3)
  wait.until { driver.find_element(:id => "cheese").displayed? }

Internal timeouts
Internally, WebDriver uses HTTP to communicate with a lot of the drivers (the  JsonWireProtocol ). By default, Net::HTTP from Ruby's standard library is used, which has a default timeout of 60 seconds. If you call Driver#get on a page that takes more than 60 seconds to load, you'll see a TimeoutError raised from Net::HTTP. You can configure this timeout (before launching a browser) by doing:
  client = Selenium::WebDriver::Remote::Http::Default.new
  client.timeout = 120 # seconds
  driver = Selenium::WebDriver.for(:remote, :http_client => client)

JavaScript dialogs
You can use webdriver to handle Javascript alert(), prompt() and confirm() dialogs. The API for all three is the same.
Note: At this time alert handling is only available in Firefox and IE (or in those browsers through the remote server), and only alerts that are generated post onload can be captured.
require "selenium-webdriver"

driver = Selenium::WebDriver.for :firefox
driver.navigate.to "http://mysite.com/page_with_alert.html"

driver.find_element(:name, 'element_with_alert_javascript').click
a = driver.switch_to.alert
if a.text == 'A value you are looking for'
  a.dismiss
else
  a.accept
end

Using Curb or your own HTTP client
For internal HTTP communication, Net::HTTP is used by default. If you e.g. have the  Curb gem  installed, you can switch to it by doing:
require 'selenium/webdriver/remote/http/curb'
include Selenium

client = WebDriver::Remote::Http::Curb.new
driver = WebDriver.for(:firefox, :http_client => client)

If you have the  net-http-persistent gem  installed, you can (as of 0.1.3) similarly use "selenium/webdriver/remote/http/persistent"to get keep-alive connections. This will significantly reduce the ephemeral ports usage of WebDriver, which is useful in  some contexts . Note that this currently only works with the remote Java server (the other servers doesn't yet support keep-alive).