Site icon Vinsguru

Selenium WebDriver – How To Design Hybrid Framework in TestNG

Overview:

As an automation test engineer, you might have noticed that some of our test steps get repeated very often in multiple tests.  In such cases, designing the tests in a such a way that it could be reused in multiple workflow is very important. Re-usability allows us to be more efficient & to write better and clean code.

Lets see how we could design reusable tests.

Sample Workflow:

Lets consider a sample application which has below workflows.

Based on the above requirements, we can come up with different workflows as shown in above picture.

  1. A new user enters details -> orders a product -> logout
  2. A new user enters details -> orders a product -> views product -> logout
  3. An existing user  -> orders a product -> views product -> logout
  4. An existing user  -> orders a product -> logout
  5. An existing user  -> views product -> logout

We might be interested in testing all these above workflows. The same workflow should also be tested for different input parameters. For ex: Different types of products, different payment methods like Credit card, promocodes etc. So writing reusuable tests is very important to maintain these tests in future.

Sample Tests:

This article just explains on writing testNG tests. So I assume that we already have Page objects for each page in the above workflow.

public class BaseTest {

    private WebDriver driver;

    @BeforeTest
    @Parameters({ "browser" })
    public void setUpDriver(String browser){
        driver = DriverManager.getDriver(browser);
    }
    
    @BeforeClass
    public void storeDriver(ITestContext ctx){
        ctx.setAttribute("driver", driver);
    }

}
public class UserDetailsTest extends BaseTest{

    private WebDriver driver;
    private UserDetailsPage userDetailsPage;

    @BeforeClass
    public void getCtx(ITestContext ctx){
        driver = ctx.getAttribute("driver");
    }
    
    @Test
    public void launch() {
        userDetailsPage = UserDetailsPage.init(driver)
                                         .launch();
        //validate if the page is loaded
        Assert.assertTrue(userDetailsPage.isAt());
    }

    @Test
    public void enterDetails() {
        userDetailsPage.enterDetails();
        Assert.assertTrue(userDetailsPage.isSubmitButtonEnabled());
    }

}
public class UserLoginTest extends BaseTest{
    
    private WebDriver driver;
    private UserLoginPage userLoginPage;

    @BeforeClass
    public void getCtx(ITestContext ctx){
        driver = ctx.getAttribute("driver");
    }
    
    @Test
    public void launch() {
        userLoginPage = UserLoginPage.init(driver)
                                         .launch();
        //validate if the page is loaded
        Assert.assertTrue(userLoginPage.isAt());
    }

    @Test
    public void login() {
        userLoginPage.enterCredentials();
        Assert.assertTrue(userLoginPage.isAuthenticated());
    }

}
public class OrderProductTest{
    
    private WebDriver driver;
    private ProductSearchPage productSearchPage;
    private OrderSummaryPage orderSummaryPage;
    private OrderConfirmationPage orderConfirmationPage;

    @BeforeClass
    public void getCtx(ITestContext ctx){
        driver = ctx.getAttribute("driver");
    }
    
    @Test
    public void productSearchTest() {
        productSearchPage = ProductSearchPage.init(driver);
        Assert.assertTrue(productSearchPage.isAt());
        productSearchPage.selectProduct(Products.A);
        productSearchPage.goToOrderSummaryPage();
    }
    
    @Test
    public void orderSummaryTest() {
        orderSummaryPage = OrderSummaryPage.init(driver);
        Assert.assertTrue(orderSummaryPage.isAt());
        orderSummaryPage.enterPaymentDetails();
    }

    @Test
    public void orderConfirmationTest() {
        orderConfirmationPage = OrderConfirmationPage.init(driver);
        Assert.assertTrue(orderConfirmationPage.isAt());
    }

}
public class ViewProductTest{
    
    private ProductViewPage productViewPage;

    @BeforeClass
    public void getCtx(ITestContext ctx){
        WebDriver driver = ctx.getAttribute("driver");
        productViewPage = ProductViewPage.init(driver);
    }
    
    @Test
    public void validate() {
        Assert.assertTrue(productViewPage.isAt());
    }

}

At this point, Your test package might look like this.

TestNG Suite:

Rest is simple. We need to call the above testNG tests in a proper sequence to create the business workflow as shown below. Now we could create N number of workflows by changing the order. In future, if we need to include any validation point, just updating in one reusable test will do.

<suite name="TestNG HyBrid Tests" parallel="none" allow-return-values="true">
    
    <parameter name="browser" value="chrome"></parameter>
    <!-- 
        by calling the TestNG reusable tests in a sequence we create different work flows.
     -->
    <test name="Check for successful user registration by order product A">
        <classes>
            <class name="com.test.UserDetailsTest" />
            <class name="com.test.OrderProductTest" />
        </classes>
    </test>
    <test name="Check for successful user registration by order product B and view Product B">
        <classes>
            <class name="com.test.UserDetailsTest" />
            <class name="com.test.OrderProductTest" />
            <class name="com.test.ViewProductTest" />
        </classes>
    </test>   
    <test name="Check if existing user can view his product">
        <classes>
            <class name="com.test.UserLoginTest" />
            <class name="com.test.ViewProductTest" />
        </classes>
    </test>       
    
</suite>

Summary:

In Continous Regression testing, the effort spent on maintenance should be as low as possible. So that team can focus on enhancing the test suite with more automated tests. But most of the time, we see a lot of red flags /  failed tests. Mostly it happens due to poorly designed flaky tests. Proper design techniques should be used for Page objects, Tests & Test Data design. Like the Page components, your tests should be also reusable if possible to reduce the maintenance effort and control flaky tests.

Happy Testing & Subscribe 🙂

 

Share This:

Exit mobile version