10-Minute Guide to Object-Oriented Programming for Automated Testers
Object Oriented (OO) simplified by examples
This is also included in the 10-minute guide series:
10-Minute Guide to Set up Test Automation using Selenium WebDriver with Ruby
10-Minute Guide to Object-Oriented Programming
Most modern programming languages support object-oriented programming (OOP). Mastering OOP is a must for software engineers and test automation engineers nowadays. This quick guide is intended for non-programmers to get a quick understanding of OO, in particular, to become automated testers.
Tables of Contents:
· Object Oriented Concept in a Nutshell
· In Ruby, everything is an object (or class)
· Class Inheritance
· Child Class Can Override Behaviours
· Use your newly learned OO knowledge to understand Automated Test Script
Object-Oriented Concept in a Nutshell
OOP sounds like a complicated concept, at least for me when I was 13 years old. It turned out to be quite simple after my father illustrated with this example:
Car is a class, a type of something, it has the following two functions (plus many more…):
accelerate
brake
My car (the one in my garage) is an object of Car, it can ‘brake’ and ‘accelerate’. I can physically drive it.
Now have a think about the statements below:
my_car = Car.new
my_car.accelerate
your_camry = Car.new
your_camry.brake
.new
creates an instance of a Class, in this case, Car. The returned instance is also known as an Object.
In Ruby, everything is an object (or class)
Ruby is a pure Object-Oriented language, comparatively, Java is not as it has primitive types. Learning OO with Ruby is easier.
a_string = "Ruby is cool"
a_string.size # => 12
iphones = ["iPhone 4s", "iPhone 5S", "iPhone 5C"]
iphones.sort #=>["iPhone 4s", "iPhone 5C", "iPhone 5S"]
a_string
is an object of String class, and iphones
is an object of class Array. Here is how to find out an object’s class.
a_string.class # => String
iphones.class # => Array
The reason we are able to use.size
and .sort
is because these functions are defined in the String and Array classes respectively.
an_object.function
Class Inheritance
Inheritance is one type of relationship between two classes. For example, seagulls and parrots are both birds, thus they share the common features of a bird.
The code below defines three classes: Bird, Seagull, and Parrot.
class Bird
def fly
puts "I am flying"
end
end
class Seagull < Bird
end
class Parrot < Bird
def speak
puts "if someone teaches me"
end
end
Inheritance can be described as “is-a” relationship. For example, we can say “Parrot is a Bird” and “Seagull is a Bird”, but not “Parrot is a Seagull”.
An object of a child class can invoke a function defined in the parent class.
a_seagull = Seagull.new
a_seagull.fly # => "I am flying"
my_parrot = Parrot.new
my_parrot.fly # => "I am flying"a_seagull.is_a?(Bird) # => true
my_parrot.is_a?(Bird) # => true
As you can see, by using inheritance, the code (defined in functions, such as fly
in Bird
class) can be reused.
A child class can define its exclusive functions, such as speak
in Parrot class.
my_parrot.speak # => "if someone teaches me"
a_seagull.speak # NoMethodError: undefined method `speak' for #<Seagull:0x..>
Child Class Can Override Behaviours
A function defined in a class is also known as “Behaviour”. A child class can override the behavior defined in its parent class, like the example below.
class Ostrich < Bird
def fly
puts "I'd rather run"
end
endo
strich = Ostrich.new
ostrich.is_a?(Bird) # => true
ostrich.fly #=> "I'd rather run"
This has a fancy term, Polymorphism, one of the most asked questions in programmer interviews. Don’t overthink it, do some OO practices, and you will get a deep understanding. For now, at least for test automation engineers, my one-line explanation will do.
Use your newly learned OO knowledge to understand Automated Test Script
Below is a raw Selenium WebDriver test that follows the Maintainable Automated Test Design.
it "Select One-way trip" do
driver.get("https://travel.agileweay.net")
login_page = LoginPage.new(driver)
login_page.enter_username("agileway")
login_page.enter_password("testwise")
login_page.click_sign_in
flight_page = FlightPage.new(driver)
flight_page.select_trip_type("oneway")
flight_page.select_depart_from("Sydney")
flight_page.select_arrive_at("New York")
flight_page.select_depart_day("02")
flight_page.select_depart_month("May 2023")
flight_page.click_continue
expect(page_text).to include("2023-05-02 Sydney to New York")
end
Two classes:
These two Page Classes represent the two web pages you see in the browser.
LoginPage
FlightPage
Three objects:
driver
, the instance of Selenium WebDriverlogin_page
andflight_page
are instances ofLoginPage
andFlightPage
respectively.
Several functions:
You can think a function in a page class is an operation that a user can perform on the web page.
enter_username
,enter_password
andclick_sign_in
inLoginPage
classselect_trip_type
,select_depart_from
,select_arrive_at
,select_depart_day
,select_depart_month
, andclick_continue
inFlightPage
class
What does a page class look like?
Here is the content of flight_page.rb
file, which defines FlightPage
class.
require File.join(File.dirname(__FILE__), "abstract_page.rb")
class FlightPage < AbstractPage
def initialize(driver)
super(driver, "") # <= TEXT UNIQUE TO THIS PAGE
end
def select_trip_type(trip_type)
driver.find_element(:xpath, "//input[@name='tripType' and @value='" + trip_type + "']").click
end
def select_depart_from(from_port)
Selenium::WebDriver::Support::Select.new(driver.find_element(:name, "fromPort")).select_by(:text, from_port)
end
# more functions ...
def click_continue
driver.find_element(:xpath,"//input[@value='Continue']").click
end
end
Now with this quick guide, do you understand the above test scripts better?