Using OOP Concepts in Selenium Framework
Encapsulation
Where: In the Page Object Model (POM), encapsulation is used by making web
elements private and exposing public methods to interact with them.
Benefit: Improves security and prevents accidental manipulation of page elements.
public class LoginPage {
  private WebDriver driver;
  private By username = By.id("username");
  private By password = By.id("password");
  private By loginButton = By.id("login");
    public LoginPage(WebDriver driver) {
      this.driver = driver;
    }
    public void enterUsername(String user) {
      driver.findElement(username).sendKeys(user);
    }
    public void enterPassword(String pass) {
      driver.findElement(password).sendKeys(pass);
    }
    public void clickLogin() {
      driver.findElement(loginButton).click();
    }
}
Without Encapsulation (Risk):
public class LoginPage {
  public WebDriver driver;
  public By username = By.id("username");
  public By password = By.id("password");
    public By loginButton = By.id("login");
    public void clickLogin() {
      driver.findElement(loginButton).click();
    }
}
LoginPage loginPage = new LoginPage();
loginPage.username = By.id("newUsername"); // Risk of accidental change
Inheritance
Where: Use a BaseClass to initialize WebDriver and common methods. Test classes
inherit from it.
Benefit: Code reusability, better management, and reduced duplication.
Base Class (BaseClass):
public class BaseClass {
  protected WebDriver driver;
    public void initializeDriver(String browser) {
      if (browser.equalsIgnoreCase("chrome")) {
          System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
          driver = new ChromeDriver();
      } else if (browser.equalsIgnoreCase("firefox")) {
          System.setProperty("webdriver.gecko.driver", "path/to/geckodriver");
          driver = new FirefoxDriver();
      }
      driver.manage().window().maximize();
    }
    public void openURL(String url) {
      driver.get(url);
    }
    public void tearDown() {
      if (driver != null) {
          driver.quit();
        }
    }
}
Test Class (LoginTest):
public class LoginTest extends BaseClass {
    @BeforeMethod
    public void setUp() {
      initializeDriver("chrome");
      openURL("https://example.com/login");
    }
    @Test
    public void testLogin() {
      LoginPage loginPage = new LoginPage(driver);
      loginPage.enterUsername("testUser");
      loginPage.enterPassword("testPassword");
      loginPage.clickLogin();
    }
    @AfterMethod
    public void tearDown() {
      super.tearDown();
    }
}
Method Overriding
Where: Override methods in child classes to provide custom functionality.
Benefit: Allows specific pages to modify base behavior (e.g., custom wait times).
BasePage:
public class BasePage {
  protected WebDriver driver;
  protected WebDriverWait wait;
    public BasePage(WebDriver driver) {
      this.driver = driver;
      this.wait = new WebDriverWait(driver, 10);
    }
  public void waitForElementVisible(By locator) {
    wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
    System.out.println("BasePage: Waiting for element visibility using default
10-second wait.");
  }
}
DashboardPage (Overriding):
public class DashboardPage extends BasePage {
    public DashboardPage(WebDriver driver) {
      super(driver);
    }
  @Override
  public void waitForElementVisible(By locator) {
    WebDriverWait customWait = new WebDriverWait(driver, 20);
    customWait.until(ExpectedConditions.visibilityOfElementLocated(locator));
    System.out.println("DashboardPage: Waiting for element visibility using custom
20-second wait.");
  }
    public void openReportsSection() {
      By reportsSection = By.id("reports");
      waitForElementVisible(reportsSection);
      driver.findElement(reportsSection).click();
    }
}
Method Overloading
Where: Use multiple methods with the same name but different parameters.
Benefit: Simplifies handling different types of inputs or optional behaviors.
BasePage with Overloaded Methods:
public class BasePage {
  protected WebDriver driver;
    public BasePage(WebDriver driver) {
      this.driver = driver;
    }
    public void enterText(By locator, String text) {
      WebElement element = driver.findElement(locator);
      element.clear();
      element.sendKeys(text);
      System.out.println("Entered text: " + text);
    }
    public void enterText(By locator, int number) {
      WebElement element = driver.findElement(locator);
      element.clear();
      element.sendKeys(String.valueOf(number));
      System.out.println("Entered number: " + number);
    }
    public void enterText(By locator, String text, boolean clearField) {
      WebElement element = driver.findElement(locator);
      if (clearField) {
          element.clear();
      }
      element.sendKeys(text);
      System.out.println("Entered text with clear option: " + text);
    }
}
Usage in RegistrationPage:
public class RegistrationPage extends BasePage {
  private By usernameLocator = By.id("username");
  private By ageLocator = By.id("age");
  private By emailLocator = By.id("email");
    public RegistrationPage(WebDriver driver) {
      super(driver);
    }
    public void registerUser(String username, int age, String email) {
      enterText(usernameLocator, username);
      enterText(ageLocator, age);
      enterText(emailLocator, email, false);
    }
}
Interface
WebDriver Interface:
public class BrowserTest {
  public static void main(String[] args) {
     System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
     WebDriver driver = new ChromeDriver();
        driver.get("https://example.com");
        System.out.println("Page Title: " + driver.getTitle());
        driver.quit();
    }
}
Key Points:
    ● WebDriver is an interface implemented by ChromeDriver, FirefoxDriver, etc.
    ● Demonstrates polymorphism.
    ● Allows flexibility to switch browsers easily.
ITestListener Interface: Used for test reporting and event handling in TestNG.
public class CustomListener implements ITestListener {
  public void onTestStart(ITestResult result) {
     System.out.println("Test started: " + result.getName());
  }
  // Other overridden methods like onTestSuccess, onTestFailure etc.
}
Abstraction
Where: Abstract away Selenium code inside reusable methods in POM classes or
utility classes.
Benefit: Hides implementation details from test classes and promotes cleaner test
code.
Example:
public abstract class AbstractPage {
  protected WebDriver driver;
    public AbstractPage(WebDriver driver) {
      this.driver = driver;
    }
    public abstract void navigateToPage();
}
public class HomePage extends AbstractPage {
  public HomePage(WebDriver driver) {
        super(driver);
    }
    @Override
    public void navigateToPage() {
      driver.get("https://example.com/home");
    }
}
Usage:
HomePage home = new HomePage(driver);
home.navigateToPage();
This demonstrates abstraction by exposing only the navigateToPage method
while hiding how the navigation is actually done.