How to Build a Selenium UI Testing Framework
Tags: selenium, test, java, automation
Published: 2023-06-12 13:26:47

## Selenium UI Testing Automation Framework
I recently created a Selenium UI testing automation framework for a sample flight/hotel booking website. The framework is based on the PageFactory and Fluent Interface patterns, and it uses Selenium, TestNG, and Extent Reports.

The framework is designed to be easy to use and maintain. It includes a set of page classes that represent the different pages of the website, as well as a set of test classes that exercise the page classes. The test classes are written using the Fluent Interface pattern, which makes them more readable and maintainable.

The framework also includes a report generator that creates interactive and detailed reports for the test results. The reports include information such as the test name, the test status, and the test steps. 

This framework can be used for UI automation testing of any web application. I am confident that it will be a valuable tool for other developers as well.

### Framework Details
#### Test Application
For this framework, I used [ClearTrip](https://cleartrip.com) as the sample flight/hotel booking website.

#### Framework - What and Why?
A framework is a pre-existing codebase that provides common functionalities and solves basic tasks for software requirements. By building on top of a framework, developers can focus on solving specific requirements without reinventing the wheel. The chosen framework serves as the foundation for implementing the software requirements specific to the project.

#### Project Structure
The project follows a standard directory structure. The page classes and related files are located in the `src/main/java/com/cleartrip/casestudy` path, while the test classes and related files can be found in the `src/test/java/com/cleartrip/casestudy` path. This separation allows for better organization and maintainability.

#### Key features of the framework:
- Page classes for each page under test, utilizing the PageFactory model to find and initialize web elements.
- Test classes that create instances of the page classes to access their methods, decoupling tests from the page elements.
- Static instantiation of the WebDriver to ensure only one instance is shared across all test classes.
- Relevant dependencies and plugins defined in the `pom.xml` file.

### Packages
#### Main Package

> The `src/main/java/` package contains the core framework code. All the page classes and related files are located in this main package. Detailed documentation can be found in the Javadoc at `<working-dir>/doc/index.html`.

#### Test Package

> The `src/test/java/` package contains the actual test classes. The subpackage `com.cleartrip.casestudy.tests` holds all the TestNG test classes related to the ClearTrip application. The Javadoc for these test classes can be found at `<working-dir>/doc/com/cleartrip/casestudy/tests/package-summary.html`.

#### Reports

> With the Extent library, we can generate interactive and detailed reports for our UI test results. The test reports can be found at `workingDir/ExtentReports/ExtentReportResults.html`.

### Installation
To set up and run the UI automation framework on your local system, follow these steps:

#### Steps to follow to set up Selenium in the local system:
**1. Install Java:**
   - Check if Java is already installed by running `java -version` and `javac -version` in the terminal.
   - If Java is not installed or an outdated version is present, install the latest Java Development Kit (JDK).

**2. Install Eclipse or any other latest IDE:**
   - Download the Eclipse installer and run it.
   - Select the option to install Eclipse for Java developers.
   - Open the Eclipse workbench.

**3. Get the Codebase:**
   - Clone the `selenium-pom-factory-fluent-pattern` repository from [GitHub](https://github.com/abu-sithik/selenium-pom-factory-fluent-pattern.git).

**4. Set up the Project in Eclipse:**
   - Open Eclipse and go to `File -> Open Project from File System`.
   - Browse the cloned project folder and open it.
   - Install the TestNG plugin for Eclipse by going to `Help -> Eclipse Marketplace` -> search for TestNG and Install it and Restart Eclipse after the installation.
   - The Maven plugin should be available by default. To verify, right-click on the project and check if there is an option called "Maven".

 **Possible issues:**
   - If there is an error in the `pom.xml` file, try the following steps:
     - Open the terminal and navigate to `Users/<profile_name>/.m2`.
     - Run `rm -r repository`.
     - Right-click on the project and select "Update project".
   - If there are errors in all import statements, try the following steps:
     - Click on the `src/main/java` folder, go to `Build Path`, and remove it from the build path.
     - Click on `src -> main -> java`, right-click, go to `Build Path`, and select "Use as Source Folder".
     - Refresh the project.

**5. Set up verification:**
   - In the test package, right-click on any Java file and select "Run As TestNG Test".

### Simple Example Test
Let's get started with a simple example of creating a test for flight booking using the page factory/fluent interface pattern.

Test Steps:
1. Go to www.cleartrip.com.
2. Select the trip type (One Way Trip).
3. Select the origin (Bangalore).
4. Select the destination (Delhi).
5. Select a date (Any random date).
6. Click on the "Search" button.

Refer to the image below to understand the page classes and test classes for different application pages:

![Package Structure](https://github.com/abu-sithik/selenium-pom-factory-fluent-pattern/blob/master/ExtentReports/package.png?raw=true)

#### Step 1: Create a Page Class
We need to create page objects for all the implemented pages in the ClearTrip site: `HomePage.java`, `FlightResultsPage.java`, `HotelResultsPage.java`, `HotelsPage.java`, and `SignInPopup.java`. These page classes will be used in the test classes to perform actions and assertions.

Let's consider the following scenario: On the home page, the user selects the flight booking option, enters valid details, and clicks the search button, which redirects them to the flight results page.

Example page class for the Home page (`HomePage.java`):

```java
public class HomePage {
    private WebDriver driver;
    private WebDriverWait wait;

    @FindBy(xpath = "//nav[@class='row fieldRow tripType']")
    private WebElement tripType;

    @FindBy(id = "FromTag")
    private WebElement origin;

    // Other web elements and methods...

    public HomePage(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
        wait = new WebDriverWait(driver, WaitTimes.TIME_5_SECONDS.getWaitTime());
    }


    // Methods for interacting with the elements and performing actions on the Home page...

    /**
     * This method launches the home page
     */
    public HomePage launch() {
        driver.get("https://www.cleartrip.com/");
        return this;
    }

    /**
     * This method selects the trip type
     *
     * @param tripTypeOption Value of Trip Type
     */
    public HomePage selectTripType(String tripTypeOption) {
        tripType.findElement(By.xpath("//input[@value='" + tripTypeOption + "']")).click();
        return this;
    }

    /**
     * This method selects the place of origin
     *
     * @param origin Value of Origin
     */
    public HomePage selectOrigin(String origin) {
        this.origin.clear();
        this.origin.sendKeys(origin);
        wait.until(ExpectedConditions.visibilityOfAllElements(originOptions));
        originOptions.get(Indices.INDEX_0.getIndexValue()).click();
        return this;
    }

    /**
     * This method clicks on the search button after
     */
    public FlightResultsPage clickSearchButton() {
        searchButton.click();
        return new FlightResultsPage(driver);
    }

    /**
     * This method clicks on the "Hotels" link in the home page
     */
    public HotelsPage clickHotelsLink() {
        hotelLink.click();
        return new HotelsPage(driver);
    }

    /**
     * This method clicks on the SignIn option which appears after clicking the "Your Trips" options
     */
    public SignInPopup clickSignInOption() {
        signIn.click();
        return new SignInPopup(driver);
    }

}
```

In the above example, we have created a page class for the ClearTrip Home page. It contains the necessary web elements and action methods associated with the Home page, initialized using the PageFactory model.

Please note that this is just an example, and you'll need to create similar page classes for other pages in the application.

#### Step 2: Create a TestBase Class

> Create a Base Test Class which is extended in all the Test Classes. So The WebDriver is instantiated in such a way that it is static and only one instance will be created and shared across all the test classes. The Driver will only quit once all the tests are done.

**TestBase.java**
```java
/**
 * Base Test Class which is extended Test Classes
 */
public abstract class TestBase {

    /**
     * Static WebDriver Instance
     */
    protected static WebDriver driver;

     
    public WebDriver getDriver() {
        return driver;
    }

    /**
     * Suite level setup method where the static instance of the WebDriver is instantiated
     */
    @BeforeSuite
    public static void initDriver() {
        
        WebDriverManager.chromedriver().setup();
    driver = new ChromeDriver();
        
    ChromeOptions options = new ChromeOptions();

        // The following statement sets the argument to disable notification in chrome when executing the tests
        options.addArguments("--disable-notifications");
        driver = new ChromeDriver(options);
        driver.manage().window().maximize();
    }

    
    /**
     * Suite level tear-down method to quit the WebDriver instance
     */
    @AfterSuite
    public void quitDriver() {
        driver.quit();
    }
}
```

#### Step 3: Create a Test Class

> In test class, instances of the page classes will be created to access methods in the page classes. Thus, tests are decoupled from the pages/ elements under test. This makes the framework more maintainable.

> So in this `FlightBookingTest` class we have to create the objects of HomePage, FlightResultsPage to access the methods available in those pages.

**FlightBookingTest.java**
```java
/**
 * Class containing test for validating search-flight results
 */
public class FlightBookingTest extends TestBase {

    /**
     * Instance of HomePage class
     */
    private HomePage homePage;

    /**
     * Instance of FlightResultsPage class
     */
    private FlightResultsPage flightResultsPage;

    /**
     * Class level test-Setup method that intantiates {@link HomePage} and {@link FlightResultsPage}
     */
    @BeforeClass
    public void testClasSetup() {
        homePage = new HomePage(driver);
        flightResultsPage = new FlightResultsPage(driver);
    }

    /**
     * Test method for verifying whether search summary is rightly displayed when searching for flights
     */
    @Test
    public void testThatResultsAppearForAOneWayJourney(Method method) {
      
        ExtentTestManager.startTest(method.getName(), "Test method for verifying whether search summary is rightly displayed when searching for flights");
        
        ExtentTestManager.getTest().log(LogStatus.INFO, "Launching the browser");
        homePage.launch() 
            .selectTripType(TripTypes.ONE_WAY.getTripType())
            .selectOrigin(Cities.BANGALORE.getCity())
            .selectDestination(Cities.Delhi.getCity())
            .selectDate()
            .clickSearchButton();
        
        ExtentTestManager.getTest().log(LogStatus.INFO, "Asserting flight search summary details");
        Assert.assertTrue(
                flightResultsPage.isSearchSummaryAvailable(),
                "Search Summary is not available after clicking the Search Button when searching for flights");
    }


}
```

In the above example, we create a test class `FlightBookingTest` that uses the `HomePage` page class to perform actions on the ClearTrip website's Home page and then asserts or performs further actions on the Flight Results page.

#### Step 4: Run the Test
To run the test, right-click on the test class `FlightBookingTest` and select "Run As TestNG Test". This will execute the test steps and display the test results in the console.

#### Extent HTML report<a name="4"></a>
> Test Reports can be found in `workingDir/ExtentReports/ExtentReportResults.html`

**Test Summary**

![alt text](https://github.com/abu-sithik/selenium-pom-factory-fluent-pattern/blob/master/ExtentReports/overview.png?raw=true)

**Specific Test details**

![alt text](https://github.com/abu-sithik/selenium-pom-factory-fluent-pattern/blob/master/ExtentReports/specificTest.gif?raw=true)

### Conclusion
The framework provides an oranized structure for creating page classes, test classes, and generating interactive test reports using Extent Reports.

By following the installation steps and the provided example, you can set up the framework on your local system and start creating UI automation tests for web applications.

For a more detailed understanding of each component and the complete source code, please refer to the [GitHub repository](https://github.com/abu-sithik/selenium-pom-factory-fluent-pattern).