Applying
Object-Oriented Programming Principles
to Test Automation Design
Angie Jones
http://angiejones.tech
@techgirl1908
Senior Director, Developer Relations
Applitools & Test Automation University
Theory vs. Application
@techgirl1908
@techgirl1908
ENCAPSULATION |
INHERITANCE |
POLYMORPHISM |
ABSTRACTION |
Pillars of OOP
@techgirl1908
Encapsulation
hide the data
@techgirl1908
public class Person {
String name;
int age;
String gender;
}
@techgirl1908
package profile;
public class Person {
private String name;
private int age;
private String gender;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
public String getGender(){
return gender;
}
public void setGender(String gender){
this.gender = gender;
}
}
@techgirl1908
@techgirl1908
@techgirl1908
public class ProfilePage extends Page{
private By bio = By.cssSelector("div[data-testid='UserDescription']");
public String getBio(){
return driver.findElement(bio).getText();
}
}
@techgirl1908
Questions
on encapsulation
@techgirl1908
Inheritance
extend data and behaviors
@techgirl1908
package profile;
public class Person {
private String name;
private int age;
private String gender;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
public String getGender(){
return gender;
}
public void setGender(String gender){
this.gender = gender;
}
}
@techgirl1908
public class Employee extends Person {
private String employeeId;
private Date startDate;
private BigDecimal salary;
public String getEmployeeId() {
return employeeId;
}
public void setEmployeeId(String employeeId) {
this.employeeId = employeeId;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public BigDecimal getSalary() {
return salary;
}
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
}
@techgirl1908
Employee angie = new Employee();
angie.setName("Angie Jones");
@techgirl1908
@techgirl1908
public class Page {
private By homeNavLink = By.cssSelector("a[data-testid='AppTabBar_Home_Link']");
private By exploreNavLink = By.cssSelector("a[data-testid='AppTabBar_Explore_Link']");
private By notificationsNavLink = By.cssSelector("a[data-testid='AppTabBar_Notifications_Link']");
private By dmNavLink = By.cssSelector("a[data-testid='AppTabBar_DirectMessage_Link']");
private By profileNavLink = By.cssSelector("a[data-testid='AppTabBar_Profile_Link']");
private By moreNavLink = By.cssSelector("a[data-testid='AppTabBar_More_Menu']");
protected WebDriver driver;
public Page(WebDriver driver){ this.driver = driver; }
private void clickNavLink(By link){
driver.findElement(link).click();
}
public void goToHome(){
clickNavLink(homeNavLink);
return new HomePage(driver);
}
public void goToExplore(){
clickNavLink(exploreNavLink);
return new ExplorePage(driver);
}
public void goToNotifications(){
clickNavLink(notificationsNavLink);
return new NotificationsPage(driver);
}
public void goToDMs(){
clickNavLink(dmNavLink);
return new DMsPage(driver);
}
}
@techgirl1908
public class NotificationPage extends Page {
//TODO: add Notification specific content
}
@Test
public void testGoToDMFromNotifications(){
Page page = new Page(driver);
NotificationsPage notificationsPage = page.goToNotifications();
//...
notificationsPage.goToDMs();
//...
}
@techgirl1908
More Inheritance
@techgirl1908
public class ProfilePage extends Page{
private By bio = By.cssSelector("div[data-testid='UserDescription']");
public String getBio(){
return driver.findElement(bio).getText();
}
}
@techgirl1908
@techgirl1908
@techgirl1908
@techgirl1908
@techgirl1908
@techgirl1908
public class ProfilePage extends Page{
private By bio = By.cssSelector("div[data-testid='UserDescription']");
public String getBio(){
return driver.findElement(bio).getText();
}
//other common methods that appear on EVERY profile page
}
@techgirl1908
public class MyProfilePage extends ProfilePage{
private By editButton = By.cssSelector("div[data-testid='EditProfileBtn']");
public EditProfilePage clickEditProfileButton(){
driver.findElement(editButton).click();
return new EditProfilePage(driver);
}
}
@techgirl1908
public class UserProfilePage extends ProfilePage {
private By dmButton = By.cssSelector("div[data-testid='sendDMFromProfile']");
public DMPage clickToDM(){
driver.findElement(dmButton).click();
return DMPage(driver);
}
}
@techgirl1908
Questions
on inheritance
@techgirl1908
Polymorphism
the ability to take multiple forms
fetch is fun!
woof
here's your dog food
woof
here's your dog food
meow
here's your cat food
@techgirl1908
public class Animal {
public void makeSound() {
System.out.println(" ");
}
}
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("woof");
}
public void fetch() {
System.out.println("fetch is fun!");
}
}
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("meow");
}
public void scratch() {
System.out.println("i scratch things");
}
}
public class Zoo {
public static void main(String[] args) {
Dog rover = new Dog();
rover.fetch();
rover.makeSound();
feed(rover);
Animal sasha = new Dog();
sasha.makeSound();
feed(sasha);
sasha = new Cat();
sasha.makeSound();
feed(sasha);
}
public static void feed(Animal animal){
if(animal instanceof Dog){
System.out.println(
"here's your dog food");
}
else if(animal instanceof Cat){
System.out.println(
"here's your cat food");
}
}
}
ProfilePage
MyProfilePage
UserProfilePage
@techgirl1908
@techgirl1908
public ProfilePage goToProfile(String username) {
driver.get(APP_URL + username);
return new ProfilePage(driver);
}
?
?
@techgirl1908
public ProfilePage goToProfile(String username) {
driver.get(APP_URL + username);
return new ProfilePage(driver);
}
@techgirl1908
public ProfilePage goToProfile(String username){
driver.get(APP_URL + username);
if(username.equalsIgnoreCase(getLoggedInUsername())){
return new MyProfilePage(driver);
}
else return new UserProfilePage(driver);
}
@Test
public void testMyBio(){
ProfilePage myProfilePage = page.goToProfile("techgirl1908");
String expectedBio = "Sr. Director, Developer Relations @Applitools & @TestAutomationU | International Keynote Speaker | Java Champion | Inventor {26 patents} | Prev. Twitter & IBM";
assertEquals(expectedBio, myProfilePage.getBio());
}
@Test
public void testDMFromProfile(){
UserProfilePage profilePage =
(UserProfilePage)page.goToProfile("Applitools");
profilePage.clickToDM();
//...
}
@techgirl1908
Questions
on polymorphism
@techgirl1908
Abstraction
provides templates to be implemented
@techgirl1908
public interface Product {
BigDecimal getPrice();
void setPrice(BigDecimal price);
String getName();
void setName(String name);
String getColor();
void setColor(String color);
}
@techgirl1908
public class Book implements Product{
private BigDecimal price;
private String name;
private String color;
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
@techgirl1908
public abstract class ListWidget {
abstract List<WebElement> getItems();
int getNumberOfItems(){
return getItems().size();
}
}
public class TweetList extends ListWidget{
private By tweet =
By.cssSelector("div[data-testid='tweet']");
List<WebElement> getItems() {
return driver.findElements(tweet);
}
}
Show your test code love!
Angie Jones
http://angiejones.tech
@techgirl1908
Senior Director, Developer Relations
Applitools & Test Automation University