Selenium WebDriver is a powerful browser automation library that can be used to control the most common web browsers in order to emulate real user / browser interactions when executing and evaluating tests.
Programming Language SDK; e.g. Ruby
Editor; e.g. VSCode
Browser Framework; e.g. Selenium + WebDriver
Browser Driver; e.g. ChromeDriver
Test Runner; e.g. RSpec
Go to RVM package manager section under the Install Ruby page and follow instructions for installing RVM which is a ruby version manager, allowing for the local system to host multiple versions of Ruby and thier respective gemsets without clashing with each other.
If you just want to install version 2.x then use your host OS package installer to install Ruby directly; e.g. for Ubuntu, run the following in a terminal session:
sudo apt install ruby
After Installation run ruby -v to check if the version of ruby requested for installation was successfully installed.
if you need to install the latest version of the gem package bundler:
gem update bundler
Click on either of the links below to install an advanced Ruby editors:
Go to the Selenium site installation page to see how to install the framework, success will look something like this:
Fetching selenium-webdriver-4.9.1.gem
Fetching websocket-1.2.9.gem
Successfully installed websocket-1.2.9
Successfully installed selenium-webdriver-4.9.1
2 gems installed
Use the following link to install web drivers for all of the major browsers:
OR: Use the following links to install gems for (deprecated) Chrome or Firefox browsers
For Chrome:
For Firefox:
Use the following link to install RSpec test runner gem file:
To check that you have installed everything you need correctly...
Create a new directory structure under your chosen dev workspace on your dev machine of the form ruby/tests/spot_check.rb
Using an editor, add the following code:
# frozen_string_literal: true
# require the selenium webdriver gem file to execute driver actions #
require "selenium-webdriver"
# require the rspec gem file to run and evaluate the test result #
require "rspec"
# require the webdrivers gem file to utilise the driver's chrome browser emulated functionality #
require "webdrivers"
RSpec.describe 'First Script' do
it 'uses eight components' do
# an object called 'driver' is set as a new instance of a chrome WebDriver created from the webdriver gem file
driver = Selenium::WebDriver.for :chrome
# driver instance http get method invoked in order to navigate to a webpage
driver.get('https://www.selenium.dev/selenium/web/web-form.html')
title = driver.title
expect(title).to eq('Web form')
driver.manage.timeouts.implicit_wait = 500
# object 'text_box' set as the result of the driver find_element method
# which uses element locator to find text based on page element name
text_box = driver.find_element(name: 'my-text')
# object 'submit_button' set as the result of the driver find_element method
# which uses element locator to find button based on page element tag_name
submit_button = driver.find_element(tag_name: 'button')
# term 'selenium' typed into text_box element
text_box.send_keys('Selenium')
# submit_button element clicked
submit_button.click
# object 'message' set as the result of the driver find_element method
# which uses element locator to find message response text based on page element id
message = driver.find_element(id: 'message')
# message response text stored in value object instance
value = message.text
# rspec matcher used to evaluate if expected value 'Recevied!' matches the returned value
expect(value).to eq('Received!')
# driver instance is now closed - always use this method at the end of all tests
driver.quit
end
end
Open a Terminal session at the file location of the newly created file and run the following:
rspec spot_check.rb
The output may contain some dependency errors because we have not created a project Gemfile, however the last line should be:
Finished in 1.78 seconds (files took 0.70235 seconds to load)
1 example, 0 failures
As a final check, fail the test by editing the rspec matcher statement line from:
expect(value).to eq('Received!')
to:
expect(value).to eq('NotReceived!')
Rerun the test as before to see a new test failure appear:
F
Failures:
1) First Script uses eight components
Failure/Error: expect(value).to eq('eceived!')
expected: "NotReceived!"
got: "Received!"
(compared using ==)
# ./spot_check.rb:37:in `block (2 levels) in <top (required)>'
Finished in 1.66 seconds (files took 0.69478 seconds to load)
1 example, 1 failure
The following examples cover basic input operations:
Key Presses
Auto complete
Implicit / Explicit Waits
Navigate and Scroll Window
Drag and Drop
Switch Context
# frozen_string_literal: true
require "selenium-webdriver"
require "webdrivers"
require "rspec"
driver = Selenium::WebDriver.for :chrome
# Drive key presses and validate the input
RSpec.describe 'Key Press Test' do
it 'tests that a single key press is returned as output of the result' do
driver.navigate.to "https://the-internet.herokuapp.com/key_presses"
# Instantiate the keypress and set to the input field for key press entry
keypress_input = driver.find_element(id: 'target')
# Send a single key press to the keypress input field
keypress_input.send_keys('B')
# Capture and validate the actual outcome against the expected result
result = driver.find_element(id: 'result').text
expect(result).to eq('You entered: B')
end
end
RSpec.describe 'Autocomplete and Waits Test' do
it 'tests that a field with autocomplete can provide a selectable autocomplete suggestion using waits' do
driver.navigate.to "https://formy-project.herokuapp.com/autocomplete"
autocomplete = driver.find_element(id: 'autocomplete')
autocomplete.send_keys('1555 PArk Blvd, Palo Alto, CA, USA')
# Implicit wait sets out a static wait time
driver.manage.timeouts.implicit_wait = 5
# Explicit wait will pause for whichever is the lower from the timeout value specified
# or until a specified event has occurred
wait = Selenium::WebDriver::Wait.new(timeout: 5)
wait.until {driver.find_element(class: 'dismissButton').displayed?}
result = driver.find_element(class: 'dismissButton')
result.click
end
end
RSpec.describe 'Autoscroll and Move to Field' do
it 'tests autoscroll and move to field' do
driver.navigate.to "https://formy-project.herokuapp.com/scroll"
name_field = driver.find_element(id: 'name')
driver.action.move_to(name_field).send_keys('Bug Bare')
date_field = driver.find_element(id: 'date')
date_field.send_keys('01/01/9999')
end
end
RSpec.describe 'Drag and Drop Test' do
it 'tests dragging and dropping of an image element from one frame to another' do
driver.navigate.to "https://the-internet.herokuapp.com/drag_and_drop"
# instantiate page objects and set by selecting element locators for each box image
image_a = driver.find_element(id: 'column-a')
image_b = driver.find_element(id: 'column-b')
# drag and drop image a into image b
driver.action.drag_and_drop(image_a,image_b).perform
end
end
RSpec.describe 'Switch Context Test' do
it 'tests the switching focus from one window to another' do
driver.navigate.to "https://the-internet.herokuapp.com/windows"
# instantiate new window link object and set by selecting css locator
new_window = driver.find_element(css: '#content>div>a')
# Open a new window clicking on the new window link
new_window.click
# switch focus to new window then back to the old one
driver.switch_to.window(driver.window_handles[1])
driver.switch_to.window(driver.window_handles[0])
driver.close
driver.quit
end
end
The following code covers page input interaction methods:
Radio Buttons
Date Pickers
Drop Downs
# frozen_string_literal: true
require "selenium-webdriver"
require "webdrivers"
require "rspec"
include Selenium::WebDriver::Support
driver = Selenium::WebDriver.for :chrome
# Drive object interactions within a page
RSpec.describe 'Test Radio Buttons' do
it 'Test that radio buttons can be selected' do
driver.navigate.to "https://formy-project.herokuapp.com/radiobutton"
# Find a radio button via it's element id
radio_button_1 = driver.find_element(id: 'radio-button-1')
radio_button_1.click
# Find a radio button via it's css selector
radio_button_2 = driver.find_element(css: 'input[value="option2"]')
radio_button_2.click
# Find a radio button via xpath
radio_button_3 = driver.find_element(xpath: 'html/body/div/div[3]/input')
radio_button_3.click
end
end
RSpec.describe 'Test Date Picker' do
it 'Test that a date can be selected using a date picker page element' do
driver.navigate.to "https://formy-project.herokuapp.com/datepicker"
# Find a datepicker object via it's id
date_input = driver.find_element(id: 'datepicker')
# Select a date using the date picker
date_input.send_keys("01/01/2099")
# Confirm the selected date
date_input.send_keys :return
end
end
RSpec.describe 'Test Dropdown Field Selection' do
it 'Test that each option in a dropdown can be selected' do
driver.navigate.to 'https://the-internet.herokuapp.com/dropdown'
# Find a dropdown on the page
option = Select.new(driver.find_element(id: 'dropdown'))
# Select option1 from the dropdown
option.select_by(:text, "Option 1")
# Validate option 1 is the selected option from the dropdown
result = driver.find_element(css: "#dropdown > option:nth-child(2)").selected?
expect(result).to eq(true)
sleep 1
option.select_by(:text, "Option 2")
# Validate option 2 is the selected option from the dropdown
result = driver.find_element(css: "#dropdown > option:nth-child(3)").selected?
expect(result).to eq(true)
sleep 1
driver.quit
end
end
The following code sample shows how methods and method calls can simplify test code by extracting common methods and then calling them in the test itself.
# frozen_string_literal: true
require "selenium-webdriver"
require "webdrivers"
require "rspec"
require "date"
# Add literals
FIRSTNAME = 'Jane'
LASTNAME = 'Doe'
JOBTITLE = 'QA'
BANNERTEXT = 'The form was successfully submitted!'
def setSubmitDate
date = DateTime.now
date.next_month.strftime("%m%d%Y")
end
def submit_form(driver)
driver.find_element(id: 'first-name').send_keys(FIRSTNAME)
driver.find_element(id: 'last-name').send_keys(LASTNAME)
driver.find_element(id: 'job-title').send_keys(JOBTITLE)
driver.find_element(id: 'radio-button-2').click
driver.find_element(id: 'checkbox-2').click
driver.find_element(css: 'option[value="2"]').click
driver.find_element(id: 'datepicker').send_keys(setSubmitDate)
driver.find_element(id: 'datepicker').send_keys :return
driver.find_element(css: '.btn.btn-lg.btn-primary').click
end
def get_banner_text(driver)
wait = Selenium::WebDriver::Wait.new(timeout: 10)
wait.until{driver.find_element(class: 'alert').displayed?}
banner = driver.find_element(class: 'alert')
banner.text
end
RSpec.describe "test form submission" do
it "uses methods to test data submission via an html form" do
driver = Selenium::WebDriver.for :chrome
driver.navigate.to "https://formy-project.herokuapp.com/form"
submit_form(driver)
actual_banner_text = get_banner_text(driver)
expect(actual_banner_text).to eq(BANNERTEXT)
driver.quit
end
end