Where We Use OOP Concepts in Automation as SDETs

Object-oriented programming (OOP) concepts are not just theoretical ideas — they are practical tools that can make your automation frameworks more robust, modular, and easier to maintain. Below, we’ll explore key OOP concepts and how they are applied across different automation frameworks, including API automation, Selenium, and Appium.

1. Abstraction

Explanation

Abstraction simplifies complex systems by hiding implementation details and exposing only the necessary parts.

In API Frameworks

In API automation, abstraction is used to hide the details of HTTP requests, allowing testers to interact with a simplified interface.

public abstract class AbstractAPIRequest {
protected String endpoint;
public AbstractAPIRequest(String endpoint) {
this.endpoint = endpoint;
}
public abstract Response sendRequest();
}
public class GetRequest extends AbstractAPIRequest {
public GetRequest(String endpoint) {
super(endpoint);
}
@Override
public Response sendRequest() {
return RestAssured.get(endpoint);
}
}

In Selenium Frameworks

In Selenium, the Page Object Model (POM) uses abstraction to separate the page structure from the test logic.

public abstract class Page {
protected WebDriver driver;
public Page(WebDriver driver) {
this.driver = driver;
}
public abstract String getPageTitle();
}
public class HomePage extends Page {
public HomePage(WebDriver driver) {
super(driver);
}
@Override
public String getPageTitle() {
return driver.getTitle();
}
}

In Appium Frameworks

In Appium, abstraction allows you to create platform-independent tests by hiding the differences between Android and iOS locators.

public abstract class MobilePage {
protected AppiumDriver driver;
public MobilePage(AppiumDriver driver) {
this.driver = driver;
}
public abstract void login(String username, String password);
}

2. Interface

Explanation

Interfaces define a contract that classes must follow, enabling polymorphism and multiple inheritance in Java.

In API Frameworks

An interface in API testing can define common operations like, which different types of requests are implemented.

public interface APIClient {
Response sendRequest();
}
public class PostRequest implements APIClient {
private String endpoint;
private Map<String, String> body;
public PostRequest(String endpoint, Map<String, String> body) {
this.endpoint = endpoint;
this.body = body;
}
@Override
public Response sendRequest() {
return RestAssured.given().body(body).post(endpoint);
}
}

In Selenium Frameworks

The WebDriver interface in Selenium is used to create browser-independent tests.

WebDriver driver = new ChromeDriver();
driver.get("https://example.com");

In Appium Frameworks

Appium uses interfaces to define common behaviors for mobile elements, which can be implemented differently for iOS and Android.

public interface MobileElement {
void tap();
void swipe();
}
public class AndroidElement implements MobileElement {
@Override
public void tap() {
// Android-specific tap implementation
}
@Override
public void swipe() {
// Android-specific swipe implementation
}
}

3. Inheritance

Explanation

Inheritance allows a new class to inherit properties and methods from an existing class, promoting code reuse.

In API Frameworks

You can create a base class for common API functionalities and extend it for specific request types.

public class BaseAPI {
protected String baseURL = "https://api.example.com";
protected Response sendRequest(String endpoint) {
return RestAssured.get(baseURL + endpoint);
}
}
public class UserAPI extends BaseAPI {
public Response getUserDetails(int userId) {
return sendRequest("/users/" + userId);
}
}

In Selenium Frameworks

A base test class can handle common setup and teardown operations in Selenium.

public class BaseTest {
WebDriver driver;
@BeforeMethod
public void setup() {
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
@AfterMethod
public void tearDown() {
driver.quit();
}
}
public class LoginTest extends BaseTest {
@Test
public void testLogin() {
driver.get("https://example.com/login");
// Perform login steps
}
}

In Appium Frameworks

Inheritance can be used to create a base page class that handles common actions for mobile pages.

public class BaseMobilePage {
protected AppiumDriver driver;
public BaseMobilePage(AppiumDriver driver) {
this.driver = driver;
}
public void tap(WebElement element) {
element.click();
}
}
public class LoginPage extends BaseMobilePage {
@FindBy(id = "username")
WebElement usernameField;
public LoginPage(AppiumDriver driver) {
super(driver);
}
public void login(String username) {
usernameField.sendKeys(username);
tap(usernameField);
}
}

4. Polymorphism

Explanation

Polymorphism allows methods to perform different tasks based on the object that invokes them, achieved through method overloading and method overriding.

In API Frameworks

Polymorphism can be utilized by overloading methods to handle different types of API requests.

public class APIClient {
public Response sendRequest(String endpoint) {
return RestAssured.get(endpoint);
}

public Response sendRequest(String endpoint, Map<String, String> params) {
return RestAssured.given().params(params).get(endpoint);
}
}

In Selenium Frameworks

Polymorphism allows you to create methods that can interact with different types of web elements in Selenium.

public interface Clickable {
void click();
}
public class Button implements Clickable {
@Override
public void click() {
// Selenium click action
}
}
public class Link implements Clickable {
@Override
public void click() {
// Selenium click action
}
}

In Appium Frameworks

Polymorphism enables different mobile elements to perform actions in platform-specific ways in Appium.

public interface Tapable {
void tap();
}
public class AndroidButton implements Tapable {
@Override
public void tap() {
// Android-specific tap action
}
}
public class iOSButton implements Tapable {
@Override
public void tap() {
// iOS-specific tap action
}
}

5. Encapsulation

Explanation

Encapsulation involves bundling data and methods that operate on that data into a single unit, protecting the internal state of an object.

In API Frameworks

Encapsulation in API testing involves bundling request details and methods into a single class.

public class APIRequest {
private String endpoint;
private Map<String, String> headers = new HashMap<>();

public APIRequest(String endpoint) {
this.endpoint = endpoint;
}
public void addHeader(String key, String value) {
headers.put(key, value);
}
public Response sendGetRequest() {
return RestAssured.given().headers(headers).get(endpoint);
}
}

In Selenium Frameworks

Encapsulation is used in Selenium to hide web elements behind public methods in Page Object classes.

public class HomePage {
@FindBy(id = "welcomeMessage")
private WebElement welcomeMessage;
public String getWelcomeMessage() {
return welcomeMessage.getText();
}
}

In Appium Frameworks

In Appium, encapsulation is used to create reusable and secure mobile page classes.

public class MobileLoginPage {
private AppiumDriver driver;
@FindBy(id = "username")
private WebElement usernameField;
public MobileLoginPage(AppiumDriver driver) {
this.driver = driver;
}
public void enterUsername(String username) {
usernameField.sendKeys(username);
}
}

6. Association

Explanation

Association defines a relationship between two classes where one class uses or is dependent on another.

In API Frameworks

In API testing, the association can be seen where different services or endpoints are interlinked.

public class OrderService {
private PaymentService paymentService;
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
public void processOrder(Order order) {
paymentService.processPayment(order.getPayment());
}
}

In Selenium Frameworks

Association in Selenium can be observed when different page objects interact with each other.

public class HomePage {
private LoginPage loginPage;
public HomePage(LoginPage loginPage) {
this.loginPage = loginPage;
}
public void login(String username, String password) {
loginPage.login(username, password);
}
}

In Appium Frameworks

In Appium, association is used when different screens of an app interact with each other.

public class HomeScreen {
private LoginScreen loginScreen;
public HomeScreen(LoginScreen loginScreen) {
this.loginScreen = loginScreen;
}
public void navigateToLogin() {
loginScreen.display();
}
}

7. Composition

Explanation

Composition is a type of association where one class is composed of one or more objects from another class, implying a strong relationship.

In API Frameworks

In API frameworks, composition can be used to build complex request payloads from smaller, reusable objects.

public class User {
private Address address;
public User(Address address) {
this.address = address;
}
public void setAddress(Address address) {
this.address = address;
}
}

In Selenium Frameworks

Composition in Selenium is used when a page is composed of multiple web elements or widgets.

public class DashboardPage {
private Sidebar sidebar;
private Header header;
public DashboardPage(Sidebar sidebar, Header header) {
this.sidebar = sidebar;
this.header = header;
}
}

In Appium Frameworks

In Appium, composition is used to create complex mobile page objects.

public class MobileDashboardPage {
private Menu menu;
private Profile profile;
public MobileDashboardPage(Menu menu, Profile profile) {
this.menu = menu;
this.profile = profile;
}
}

8. Aggregation

Explanation

Aggregation is a weaker form of composition where the lifetime of the contained object does not depend on the container class.

In API Frameworks

In API frameworks, aggregation is used when one service class uses another service class.

public class OrderService {
private List<Order> orders;
public void addOrder(Order order) {
orders.add(order);
}
}

In Selenium Frameworks

Aggregation in Selenium can be used when multiple elements or components are part of a single page but have independent lifecycles.

public class ShoppingCart {
private List<Product> products;
public ShoppingCart(List<Product> products) {
this.products = products;
}
public void addProduct(Product product) {
products.add(product);
}
}

In Appium Frameworks

In Appium, aggregation can be used when different parts of a screen are combined without being strongly dependent on one another.

public class MobileShoppingCart {
private List<MobileProduct> mobileProducts;
public void addMobileProduct(MobileProduct product) {
mobileProducts.add(product);
}
}

By using these OOP principles in your automation frameworks, you not only enhance code readability and reusability but also make your tests more maintainable and scalable. These principles are the backbone of any robust automation framework, ensuring that your tests are not only effective but also adaptable to change.

Comments