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

Applying OOP to Test Automation Design

By Angie Jones

Applying OOP to Test Automation Design

Practical examples of how to translate object-oriented programming concepts to automation framework design.

  • 30,516