Let's break down how Object-Oriented Programming (OOP) Concepts can be applied in a test automation framework using a simple example in Java with Selenium.
1. Encapsulation
Encapsulation involves grouping related data and methods into classes. This ensures that data is hidden from outside interference.
public class Landingpage {
WebDriver driver;
public Landingpage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
@FindBy(xpath="//a[@title='My Account']")
WebElement Myaccountdropdown;
@FindBy(linkText="Login")
WebElement loginoption;
public WebElement Myaccountdropdown() {
return Myaccountdropdown;
}
public WebElement loginoption() {
return loginoption;
}
}
2. Inheritance
Inheritance allows us to reuse common code across different classes.
public class BaseTest {
protected WebDriver driver;
@BeforeMethod
public void setUp() {
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
driver.get(" http://tutorialsninja.com/demo/"); }
@AfterMethod
public void tearDown() {
driver.quit(); } }
Now, any test class can inherit from Base Test to reuse the setup and teardown methods.
public class LoginTest extends BaseTest {
@Test public void validLoginTest() {
LoginPage loginPage = new LoginPage(driver);
loginPage.enterUsername("user");
loginPage.enterPassword("pass");
loginPage.clickLoginButton();
}
}
3.Abstraction
Abstraction hides the complexity of the code by providing a simple interface. Providing a clear and reusable interface for interacting with web pages.
public class AccountPage {
WebDriver driver;
public AccountPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
@FindBy(linkText="Edit your account information")
WebElement EditLinkoption;
public WebElement EditLinkoption() {
return EditLinkoption;
}
}
---------------------------------------------
public class LoginTest extends Base {
WebDriver driver;
@Test
public void Login() throws IOException {
driver = intializeDriver();
driver.get(prop.getProperty("url"));
Landingpage landingPage = new Landingpage(driver);
landingPage.Myaccountdropdown().click();
landingPage.loginoption().click();
LoginPage loginpage = new LoginPage(driver);
loginpage.UseridField().sendKeys(prop.getProperty("email"));
loginpage.Password().sendKeys(prop.getProperty("password"));
loginpage.Loginbtn().click();
AccountPage accountPage = new AccountPage(driver);
Assert.assertTrue(accountPage.EditLinkoption().isDisplayed());
}
@AfterMethod
public void Closure() {
driver.close();
}
}
4.Polymorphism
Polymorphism in Object-Oriented Programming (OOP) comes in two main types:
1.Compile-Time (Static) Polymorphism
2. Run-Time (Dynamic) Polymorphism.
Here's how they apply in a test automation framework:
1. Compile-Time (Static) Polymorphism
This type of polymorphism is achieved through method overloading . it’s primarily implemented via method overloading.
Example of Method Overloading in a Test Automation Framework:
public class SearchPage {
private WebDriver driver;
public SearchPage(WebDriver driver) { this.driver = driver; } // Method to search by text
public void search(String query) {
driver.findElement(By.name("q")).sendKeys(query + Keys.ENTER); } // Overloaded method to search by text with category
public void search(String query, String category)
{ driver.findElement(By.name("q")).sendKeys(query + " " + category + Keys.ENTER); } // Overloaded method to search with an advanced filter
public void search(String query, boolean isAdvanced) {
if (isAdvanced) { // Code to apply advanced filter } driver.findElement(By.name("q")).sendKeys(query + Keys.ENTER);
}
}
In this example, the search() method is overloaded to handle different types of search operations based on the parameters provided.
2. Run-Time (Dynamic) Polymorphism
This type of polymorphism is achieved through method overriding, where a subclass provides a specific implementation of a method that is already defined in its superclass or interface. The decision about which method to execute is made at runtime.
Example of Method Overriding in a Test Automation Framework:
Here’s where your example comes in:
public interface TestPage {
void load();
}
public class HomePage implements TestPage {
private WebDriver driver;
public HomePage(WebDriver driver) {
this.driver = driver;
}
@Override public void load()
{
driver.get(" http://tutorialsninja.com/demo/");
}
}
public class DashboardPage implements TestPage {
private WebDriver driver;
public DashboardPage(WebDriver driver) {
this.driver = driver;
}
@Override
public void load() {
driver.get("https://example.com/dashboard");
}
}
Here, both HomePage and DashboardPage implement the TestPage interface and provide their specific implementation of the load() method. This is an example of dynamic polymorphism because the actual method that gets executed (either HomePage.load() or DashboardPage.load()) is determined at runtime, depending on the object type.
Example Usage in a Test:
public class NavigationTest {
@Test
public void testNavigation() {
WebDriver driver = new ChromeDriver();
TestPage page = new HomePage(driver);
page.load(); // This will call HomePage.load()
page = new DashboardPage(driver);
page.load(); // This will call DashboardPage.load()
driver.quit();
}
}
Execution Flow:
When you call homePage.load();, the load method in HomePage will execute first, navigating to http://tutorialsninja.com/demo/.
Next, when you call dashboardPage.load();, the load method in DashboardPage will execute, navigating to https://example.com/dashboard.
5. INTERFACE
Basic statement we all know in Selenium is WebDriver driver = new FirefoxDriver();
Detailed explanation on why we write WebDriver driver = new FirefoxDriver(); in Selenium.
WebDriver itself is an Interface. So based on the above statement WebDriver driver = new FirefoxDriver(); we are initializing Firefox browser using Selenium WebDriver. It means we are creating a reference variable (driver) of the interface (WebDriver) and creating an Object. Here WebDriver is an Interface as mentioned earlier and FirefoxDriver is a class.
In this example:
Encapsulation :is demonstrated in LoginPage by grouping the elements and actions related to the login page.
Inheritance :is shown by LoginTest extending BaseTest to reuse setup and teardown methods.
Abstraction :is applied in AbstractTest, hiding the implementation details of the runTest() method.
Polymorphism : is used in TestPage, allowing different pages (`HomePage`, DashboardPage) to implement the load() method.
Interface:Integrating interfaces into a Selenium BDD framework provides a structured and maintainable approach to test automation.
This structure makes the test automation framework more modular, reusable, and easier to maintain.
Happy Testing!
Kommentarer