Data-Driven Testing in Selenium

What is Data-Driven Testing?

Data-driven testing is a framework where test input and output data are stored in external data sources like Excel, CSV, or databases. The test scripts execute multiple times with different sets of data, improving test coverage and reducing redundancy.

Benefits of Data-Driven Testing

Common Data vs Test Script Data

When designing automated tests, it's essential to separate **common data** (data that applies to multiple test cases or is environment-specific) from **test script data** (data specific to individual test cases). This ensures that the tests are more flexible and easier to maintain.

What is Common Data?

Common data includes information such as application URLs, credentials, or system settings that multiple test scripts share. For example, the base URL of a website or global login credentials can be considered common data.

Example:


            url=https://shariqsp.com
            username=admin
            password=admin123
            

What is Test Script Data?

Test script data is specific to individual test cases. This includes inputs, expected outputs, or variations in data that change from test to test. For example, different sets of user details when testing a signup form.

Example:


            username=testuser1
            password=pass1234
            email=testuser1@example.com
            

Why Should We Avoid Hardcoding Data in Test Scripts?

Hardcoding data directly into test scripts is considered a poor practice because it limits the flexibility, maintainability, and scalability of your test framework. Here’s why:

1. Flexibility and Reusability

Hardcoding data makes the test script rigid. If the data changes, you must modify the test script, resulting in unnecessary maintenance. By storing the data in external files like **property files**, **Excel**, or **CSV**, the script remains the same, but the data can change as needed.

2. Environment Changes

If the environment changes (e.g., the URL or credentials for the test server), hardcoded data means you'll need to manually edit every script where this data is present. By separating data into external sources, only the data file needs updating, making it easier to switch between environments.

3. Scalability

When expanding test coverage, hardcoded data limits the scalability of your test suite. With external data sources, you can quickly add more data sets without modifying the script logic. For example, you can easily add more rows to an Excel file or database without changing the test scripts.

What Happens If You Hardcode Data? (Scenario)

Consider a scenario where your company changes the password policy, and all passwords need to include special characters. If you have hardcoded passwords in 50 test scripts, each one needs to be modified. This is time-consuming and prone to errors.

Scenario:

You have a login script with hardcoded data:


            public class LoginTest {
                public void loginTest() {
                    WebDriver driver = new ChromeDriver();
                    driver.get("https://shariqsp.com/login");
        
                    // Hardcoded credentials
                    driver.findElement(By.id("username")).sendKeys("testuser");
                    driver.findElement(By.id("password")).sendKeys("password123");
        
                    driver.findElement(By.id("loginButton")).click();
                }
            }
            

If the username or password changes, or if you're testing in different environments (staging, production, etc.), you will have to manually update every instance of this hardcoded data. Instead, by using external data, you could simply update the **property file** or **Excel sheet** without touching the script logic.

Advantages of Data-Driven Testing

Data-driven testing offers numerous benefits that improve the efficiency, maintainability, and flexibility of test automation. By separating test data from test logic, data-driven testing enables testers to execute the same test scripts with multiple sets of data, increasing coverage and reducing redundancy.

1. Increased Test Coverage

With data-driven testing, a single test script can be run with multiple data sets, covering a wide range of input scenarios. This significantly improves test coverage as you can test different permutations of input values and edge cases without duplicating test scripts.

2. Reusability of Test Scripts

Since the test data is stored separately, the same test script can be reused across different test cases. This helps reduce redundancy, as the script remains unchanged while the input data can be modified as needed.

3. Easy Maintenance

One of the primary benefits of data-driven testing is that if the data changes, there’s no need to update the test script itself. You only need to update the external data sources (such as Excel or property files), making it much easier to maintain and adapt tests when requirements change.

4. Flexibility Across Environments

By storing test data externally, data-driven tests can be easily adapted to run across different environments. For example, you can store environment-specific values like URLs, credentials, or settings in external files and switch between them depending on the test environment (e.g., staging, production).

5. Enhanced Test Efficiency

Data-driven testing reduces the need for writing multiple test scripts for similar functionalities. Instead of writing separate tests for each scenario, you can run a single test script with various data sets, saving time and effort.

6. Better Test Reporting

By running the same script with different data sets, you can generate more comprehensive reports. Each data set’s result is tracked individually, making it easier to identify which scenarios pass or fail.

7. Supports Multiple Data Formats

Data-driven testing allows you to source data from multiple formats such as Excel, CSV, JSON, databases, and more. This flexibility lets you choose the best data storage mechanism for your tests, making it adaptable to various environments and data types.

8. Eliminates Hardcoding

By externalizing the data, you avoid hardcoding values within your test scripts. This makes your test framework cleaner and more modular, as the test logic is kept separate from the data.

9. Cross-Browser Testing Support

Data-driven testing allows you to run the same test script across multiple browsers (e.g., Chrome, Firefox, Safari) by supplying different browser configurations as data. This ensures that your application works consistently across different browsers.

Example: You can store browser types (e.g., Chrome, Firefox) in an Excel or property file and run the tests with different browsers automatically.

10. Suite Execution with Different Credentials

Data-driven testing can handle multiple sets of credentials (e.g., different user roles or permissions). By feeding different credentials from external files like Excel or CSV, you can test your application with multiple users without modifying the script.

Example: You can run the same suite with different roles such as admin, user, or guest, by fetching credentials from the data file and executing the test accordingly.

Tools and Libraries Needed for Data-Driven Testing

Data-driven testing in Selenium relies on various libraries and tools to read and manage data from external sources. Here are some of the commonly used tools and libraries:

1. Property Files

Property files are simple text files that store key-value pairs. They are widely used to manage configuration data such as environment URLs, login credentials, and other reusable data across tests. Property files allow test scripts to be more flexible by externalizing data, avoiding hardcoding.


            # Example config.properties file
            url=https://shariqsp.com
            username=testuser
            password=password123
            

2. Apache POI (For Excel Files)

Apache POI is a Java library that allows you to read and write Excel files (`.xls` and `.xlsx`). It is commonly used in data-driven testing to handle test data stored in Excel files.


            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>5.0.0</version>
            </dependency>
            

3. OpenCSV (For CSV Files)

OpenCSV is a lightweight library that simplifies reading and writing CSV files in Java. It is an excellent choice for handling test data stored in CSV format.


            <dependency>
                <groupId>com.opencsv</groupId>
                <artifactId>opencsv</artifactId>
                <version>5.4</version>
            </dependency>
            

4. Jackson (For JSON Files)

Jackson is a powerful Java library for parsing JSON data. It is helpful when dealing with test data stored in JSON format and can easily convert JSON to Java objects and vice versa.


            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.12.3</version>
            </dependency>
            

5. MySQL/JDBC (For Database Testing)

Data-driven tests can also pull data from relational databases such as MySQL. The Java Database Connectivity (JDBC) API is commonly used to connect and query databases for dynamic data retrieval in test cases.


            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.23</version>
            </dependency>
            

6. TestNG (For Data Providers)

TestNG is a powerful testing framework that supports data-driven testing through the `@DataProvider` annotation. By integrating it with external data sources (e.g., Excel, CSV, Property Files), TestNG facilitates running tests with multiple sets of data.


            <dependency>
                <groupId>org.testng</groupId>
                <artifactId>testng</artifactId>
                <version>7.4.0</version>
            </dependency>
            

Achieving Cross-Browser and Cross-Platform Testing Using Property Files

Cross-browser and cross-platform testing is essential for ensuring that web applications function correctly across various browsers and operating systems. One effective approach to managing these tests is by utilizing property files. Property files allow you to externalize configuration data, making it easier to manage different settings without hardcoding them in your tests.

Benefits of Using Property Files

Setting Up Property Files

Follow these steps to set up and utilize property files for cross-browser and cross-platform testing:

  1. Create a Property File: Create a file named config.properties to store the configuration settings.
# Example config.properties
        # Browser Configuration
        browser.chrome.path=/path/to/chromedriver
        browser.firefox.path=/path/to/geckodriver
        browser.safari.path=/path/to/safaridriver
        
        # Browser Options
        browser.chrome.options=--headless
        browser.firefox.options=--headless
        
        # Platform Configuration
        platform.windows=true
        platform.mac=false
        platform.linux=true
        
  1. Load the Property File: Use a properties loader in your testing framework to read the configurations from the config.properties file.
import java.io.FileInputStream;
        import java.io.IOException;
        import java.util.Properties;
        
        public class ConfigLoader {
            private Properties properties;
        
            public ConfigLoader(String propertyFilePath) {
                properties = new Properties();
                try {
                    FileInputStream fileInputStream = new FileInputStream(propertyFilePath);
                    properties.load(fileInputStream);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        
            public String getProperty(String key) {
                return properties.getProperty(key);
            }
        }
        
  1. Utilize Properties in Tests: In your test scripts, you can use the loaded properties to set up the desired browser and platform.
import org.openqa.selenium.WebDriver;
        import org.openqa.selenium.chrome.ChromeDriver;
        import org.openqa.selenium.firefox.FirefoxDriver;
        
        public class CrossBrowserTest {
            public static void main(String[] args) {
                ConfigLoader configLoader = new ConfigLoader("config.properties");
                String browser = System.getProperty("browser", "chrome"); // Default to Chrome
        
                WebDriver driver;
        
                if (browser.equalsIgnoreCase("firefox")) {
                    System.setProperty("webdriver.gecko.driver", configLoader.getProperty("browser.firefox.path"));
                    driver = new FirefoxDriver();
                } else if (browser.equalsIgnoreCase("chrome")) {
                    System.setProperty("webdriver.chrome.driver", configLoader.getProperty("browser.chrome.path"));
                    driver = new ChromeDriver();
                } else {
                    throw new IllegalArgumentException("Browser not supported: " + browser);
                }
        
                // Example test steps
                driver.get("https://www.example.com");
                System.out.println("Title: " + driver.getTitle());
                driver.quit();
            }
        }
        

Running Tests on Different Platforms

To run your tests on different platforms, you can modify the properties file or pass parameters dynamically at runtime.

  1. Modify the Properties: You can set properties in config.properties for different platforms and browsers.
  2. Dynamic Execution: You can pass the browser type or platform from the command line when executing your tests.
# Example command to run a test with a specified browser
        mvn test -Dbrowser=firefox
        

Conclusion

Using property files for cross-browser and cross-platform testing simplifies the management of configuration settings and enhances the flexibility of test execution. This approach enables you to easily switch browsers and platforms without changing your test code, ensuring comprehensive testing across various environments.

Using Excel in Data-Driven Testing

Data-driven testing (DDT) is a testing methodology that uses data stored in external files to execute tests. Excel is a popular choice for storing test data due to its ease of use and widespread familiarity. Here are some reasons why we should use Excel in data-driven testing:

Benefits of Using Excel

Scenarios for Using Excel in Data-Driven Testing

  1. User Registration Testing: In scenarios where multiple user accounts need to be created for testing, Excel can hold user information like username, password, and email. This allows for easy bulk testing of user registration functionalities.
  2. Login Validation: Excel can store various combinations of valid and invalid credentials to test the login functionality. This helps ensure that the application handles all scenarios appropriately.
  3. Data Import Features: If your application allows users to import data, Excel can be used to validate that the application correctly processes different formats and structures of input data.

Apache POI

Apache POI is a powerful Java library used for reading and writing Microsoft Office documents, including Excel files. It provides a range of APIs to manipulate Excel sheets, allowing you to perform tasks such as reading data from Excel files, writing data back into them, and formatting cells.

Apache POI Class Diagram with Inheritance, Key Methods, and Class/Interface Distinction

This diagram highlights the important classes and interfaces used in the Apache POI library for reading and writing Excel files. It also includes the key methods associated with each class. Arrows indicate inheritance or implementation relationships between interfaces and classes, making the structure clear.

Diagram Overview

                                            +----------------------+
                                            |      Workbook        |<-------------+
                                            +----------------------+              |
                                            | + createSheet()      |              |
                                            | + getSheetAt()       |              |
                                            | + write()            |              |
                                            +----------------------+              |
                                                     |                            |
                                                     | implements                 |
                                            +----------------------+              +----------------------+
                                            |     XSSFWorkbook     |<-------------|    HSSFWorkbook      |
                                            +----------------------+              +----------------------+
                                            | (for .xlsx files)    |              | (for .xls files)     |
                                            +----------------------+              +----------------------+
                                                     |
                                            +----------------------+
                                            |        Sheet         |
                                            +----------------------+
                                            | + createRow()        |
                                            | + getRow()           |
                                            | + getRowIterator()   |
                                            +----------------------+
                                                    |                         
                                 +------------------+-------------------+                     
                                 |                                      |
                    +----------------------+                +----------------------+
                    |      XSSFSheet       |                |      HSSFSheet       |
                    +----------------------+                +----------------------+
                    | (for .xlsx sheets)   |                | (for .xls sheets)    |
                    +----------------------+                +----------------------+
                                 |
                        +----------------------+
                        |        Row           |
                        +----------------------+
                        | + createCell()       |
                        | + getCell()          |
                        | + getCellIterator()  |
                        +----------------------+
                                 |
                        +-----------------------+
                        |        Cell           |
                        +-----------------------+
                        | + setCellValue()      |
                        | + getStringCellValue()|
                        | + setCellType()       |
                        +-----------------------+
                

Explanation of Key Classes, Interfaces, and Methods

  • Workbook (Interface)
    • createSheet(String name): Creates a new sheet with the specified name.
    • getSheetAt(int index): Retrieves the sheet at the specified index.
    • write(OutputStream stream): Writes the workbook to the specified output stream.
  • XSSFWorkbook (Class)
    • Implements Workbook for `.xlsx` format.
  • HSSFWorkbook (Class)
    • Implements Workbook for `.xls` format.
  • Sheet (Interface)
    • createRow(int rowNum): Creates a new row in the sheet at the specified index.
    • getRow(int rowNum): Retrieves the row at the specified index.
    • getRowIterator(): Returns an iterator for the rows in the sheet.
  • XSSFSheet (Class)
    • Implements Sheet for `.xlsx` format.
  • HSSFSheet (Class)
    • Implements Sheet for `.xls` format.
  • Row (Interface)
    • createCell(int columnIndex): Creates a new cell in the row at the specified column index.
    • getCell(int columnIndex): Retrieves the cell at the specified column index.
    • getCellIterator(): Returns an iterator for the cells in the row.
  • Cell (Interface)
    • setCellValue(String value): Sets the value of the cell to a String.
    • getStringCellValue(): Retrieves the cell value as a String.
    • setCellType(CellType type): Sets the cell type (e.g., STRING, NUMERIC).

The diagram highlights key classes and interfaces in the Apache POI library. Interfaces like Workbook, Sheet, Row, and Cell define the contract for manipulating Excel files, while classes like XSSFWorkbook and HSSFWorkbook provide concrete implementations for working with .xlsx and .xls formats respectively. By understanding the relationship between these interfaces and classes, you can effectively use Apache POI to perform operations on Excel files.

Program to Read Data from Excel for User Creation Module

Excel Data

Username Password Email
user1 pass1 user1@example.com
user2 pass2 user2@example.com
user3 pass3 user3@example.com

The following program reads user data from an Excel file to automate the user creation process:

import org.apache.poi.ss.usermodel.*;
        import org.apache.poi.xssf.usermodel.XSSFWorkbook;
        import java.io.FileInputStream;
        import java.io.IOException;
        
        public class ReadExcel {
            public static void main(String[] args) {
                String excelFilePath = "user_data.xlsx"; // Path to the Excel file
                try (FileInputStream fileInputStream = new FileInputStream(excelFilePath);
                     Workbook workbook = new XSSFWorkbook(fileInputStream)) {
                     
                    Sheet sheet = workbook.getSheetAt(0); // Get the first sheet
                    for (Row row : sheet) {
                        String username = row.getCell(0).getStringCellValue();
                        String password = row.getCell(1).getStringCellValue();
                        String email = row.getCell(2).getStringCellValue();
                        // Use the data for user creation logic
                        System.out.println("Creating user: " + username + ", Email: " + email);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        

Program Explanation:

  1. Import Statements: The necessary classes from the Apache POI library are imported to handle Excel files.
  2. Main Method: The main method serves as the entry point for the program.
  3. File Input Stream: A FileInputStream is created to read the Excel file located at the specified path.
  4. Workbook Creation: An instance of Workbook is created using XSSFWorkbook, which handles .xlsx files.
  5. Accessing the Sheet: The first sheet of the workbook is accessed using getSheetAt(0).
  6. Iterating Rows: A loop iterates through each row of the sheet, reading the username, password, and email from the first three cells of each row.
  7. Using the Data: For demonstration, the program prints out the username and email, simulating user creation.
  8. Error Handling: An IOException is caught if there are issues reading the file, and the stack trace is printed for debugging.

Reading Excel Data Based on Conditions Using Apache POI

1. Program to Retrieve Row Data Based on a Condition

The following program demonstrates how to retrieve a row of data from an Excel sheet based on a condition using Apache POI. In this case, we will retrieve a row where a specific cell in a column matches a given value (e.g., retrieve a row where "Name" equals "John").

            // Required imports
            import org.apache.poi.ss.usermodel.*;
            import org.apache.poi.xssf.usermodel.XSSFWorkbook;
            import java.io.FileInputStream;
            import java.io.IOException;
            
            public class ReadRowBasedOnCondition {
            
                public static void main(String[] args) throws IOException {
                    // Path to Excel file
                    FileInputStream fis = new FileInputStream("path_to_your_file.xlsx");
            
                    // Create Workbook instance for .xlsx file
                    Workbook workbook = new XSSFWorkbook(fis);
                    
                    // Get the first sheet (0-indexed)
                    Sheet sheet = workbook.getSheetAt(0);
                    
                    // Iterate over rows
                    for (Row row : sheet) {
                        // Assume column 0 has names, we are looking for "John"
                        Cell cell = row.getCell(0);
                        if (cell.getStringCellValue().equals("John")) {
                            // Print all cell values in the row
                            for (Cell c : row) {
                                System.out.print(c + " ");
                            }
                            System.out.println(); // New line after printing the row
                        }
                    }
            
                    // Close the workbook and file input stream
                    workbook.close();
                    fis.close();
                }
            }
                

Explanation of the Program (Retrieve Row)

  • FileInputStream: Opens the Excel file from the given path.
  • Workbook: An instance of XSSFWorkbook is created to handle `.xlsx` files.
  • Sheet: The first sheet of the Excel workbook is accessed using getSheetAt(0).
  • Row Iteration: The program iterates over each row in the sheet.
  • Condition Check: The program checks if the first cell in the row (column 0) matches the desired condition (i.e., the name is "John").
  • Print Row: If the condition is met, the entire row's cell values are printed.
  • Close Resources: The workbook and file input stream are closed to free resources.

2. Program to Read Column Data

This program demonstrates how to read all data from a specific column in an Excel sheet. In this case, we will read and print all data from the second column (index 1).

            // Required imports
            import org.apache.poi.ss.usermodel.*;
            import org.apache.poi.xssf.usermodel.XSSFWorkbook;
            import java.io.FileInputStream;
            import java.io.IOException;
            
            public class ReadColumnData {
            
                public static void main(String[] args) throws IOException {
                    // Path to Excel file
                    FileInputStream fis = new FileInputStream("path_to_your_file.xlsx");
            
                    // Create Workbook instance for .xlsx file
                    Workbook workbook = new XSSFWorkbook(fis);
            
                    // Get the first sheet (0-indexed)
                    Sheet sheet = workbook.getSheetAt(0);
            
                    // Specify the column to read (e.g., column 1 for the second column)
                    int columnIndex = 1;
            
                    // Iterate over rows and get the cell in the specific column
                    for (Row row : sheet) {
                        Cell cell = row.getCell(columnIndex);
                        if (cell != null) { // Check if cell exists
                            System.out.println(cell);
                        }
                    }
            
                    // Close the workbook and file input stream
                    workbook.close();
                    fis.close();
                }
            }
                

Explanation of the Program (Read Column)

  • FileInputStream: The Excel file is opened for reading from the specified path.
  • Workbook: A XSSFWorkbook instance is used to handle `.xlsx` files.
  • Sheet: The program accesses the first sheet of the workbook using getSheetAt(0).
  • Column Index: The program specifies the column index to read (in this case, column 1, which is the second column).
  • Row Iteration: The program iterates over each row and retrieves the cell in the specified column.
  • Null Check: The program checks whether the cell exists to avoid NullPointerException for rows that do not have a value in the target column.
  • Print Cell: The value of the cell is printed if it exists.
  • Close Resources: The workbook and file input stream are closed at the end to release resources.

Use Cases for the Above Programs

  • Row-based Condition Retrieval: This program is useful when you need to find a specific record in an Excel sheet based on a condition. For example, if you are looking for all user details where the username is "John".
  • Column Data Reading: Reading a specific column is helpful for scenarios where you want to extract data from a single field across multiple rows, such as retrieving all email addresses from a column in a user database.

Program to Read Multiple Data from Excel

The following program demonstrates how to read multiple rows of data from an Excel sheet:

public class ReadMultipleData {
            public static void main(String[] args) {
                String excelFilePath = "user_data.xlsx";
                try (FileInputStream fileInputStream = new FileInputStream(excelFilePath);
                     Workbook workbook = new XSSFWorkbook(fileInputStream)) {
                     
                    Sheet sheet = workbook.getSheetAt(0);
                    for (Row row : sheet) {
                        String username = row.getCell(0).getStringCellValue();
                        String password = row.getCell(1).getStringCellValue();
                        String email = row.getCell(2).getStringCellValue();
                        // Use the data for various test scenarios
                        System.out.println("Username: " + username + ", Password: " + password + ", Email: " + email);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        

Program Explanation:

  1. Import Statements: Similar to the previous program, necessary imports from Apache POI are included.
  2. Main Method: The program execution begins in the main method.
  3. File Input Stream: A FileInputStream is created for the Excel file to read data.
  4. Workbook Creation: The XSSFWorkbook object is instantiated to handle the .xlsx file.
  5. Accessing the Sheet: The first sheet is accessed for reading data.
  6. Iterating Rows: A loop is used to go through each row in the sheet, retrieving the username, password, and email from the respective cells.
  7. Using the Data: The retrieved data is printed, showcasing how each piece of information can be used in different test scenarios.
  8. Error Handling: Exception handling is applied to catch any potential input/output exceptions.

Program to Write Data Back into Excel

This program demonstrates how to write user data back into an Excel file:

import org.apache.poi.ss.usermodel.*;
        import org.apache.poi.xssf.usermodel.XSSFWorkbook;
        import java.io.FileOutputStream;
        import java.io.IOException;
        
        public class WriteExcel {
            public static void main(String[] args) {
                String excelFilePath = "user_data_output.xlsx";
                try (Workbook workbook = new XSSFWorkbook();
                     FileOutputStream fileOutputStream = new FileOutputStream(excelFilePath)) {
                     
                    Sheet sheet = workbook.createSheet("User Data");
                    Row headerRow = sheet.createRow(0);
                    headerRow.createCell(0).setCellValue("Username");
                    headerRow.createCell(1).setCellValue("Password");
                    headerRow.createCell(2).setCellValue("Email");
                    
                    Row dataRow = sheet.createRow(1);
                    dataRow.createCell(0).setCellValue("user4");
                    dataRow.createCell(1).setCellValue("pass4");
                    dataRow.createCell(2).setCellValue("user4@example.com");
        
                    workbook.write(fileOutputStream);
                    System.out.println("Data written to Excel file successfully.");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        

Program Explanation:

  1. Import Statements: The necessary Apache POI classes are imported for writing to Excel.
  2. Main Method: The main method initializes the program.
  3. Workbook Creation: A new XSSFWorkbook instance is created to generate a new Excel file.
  4. File Output Stream: A FileOutputStream is created to specify where to save the Excel file.
  5. Creating a Sheet: A new sheet named "User Data" is created in the workbook.
  6. Header Row: A header row is created to define the columns (Username, Password, Email).
  7. Data Row: A new data row is created, populating it with example user data.
  8. Writing to File: The workbook is written to the output stream, saving the data to the specified Excel file.
  9. Error Handling: Any input/output exceptions are caught and logged.

Integrating Selenium with Excel for Data-Driven Testing

Below is a program that integrates Selenium with Excel to automate user registration by reading user data and performing actions in a web application:

import org.openqa.selenium.By;
        import org.openqa.selenium.WebDriver;
        import org.openqa.selenium.chrome.ChromeDriver;
        import org.apache.poi.ss.usermodel.*;
        import org.apache.poi.xssf.usermodel.XSSFWorkbook;
        import java.io.FileInputStream;
        import java.io.IOException;
        
        public class SeleniumExcelIntegration {
            public static void main(String[] args) {
                String excelFilePath = "user_data.xlsx";
                System.setProperty("webdriver.chrome.driver", "path/to/chromedriver"); // Specify the path to chromedriver
                WebDriver driver = new ChromeDriver();
                driver.get("http://example.com/register"); // Navigate to the registration page
                
                try (FileInputStream fileInputStream = new FileInputStream(excelFilePath);
                     Workbook workbook = new XSSFWorkbook(fileInputStream)) {
                     
                    Sheet sheet = workbook.getSheetAt(0);
                    for (Row row : sheet) {
                        String username = row.getCell(0).getStringCellValue();
                        String password = row.getCell(1).getStringCellValue();
                        String email = row.getCell(2).getStringCellValue();
                        
                        // Fill in the registration form
                        driver.findElement(By.id("username")).sendKeys(username);
                        driver.findElement(By.id("password")).sendKeys(password);
                        driver.findElement(By.id("email")).sendKeys(email);
                        driver.findElement(By.id("registerBtn")).click(); // Submit the form
                        
                        // Wait for some time for the registration to complete
                        Thread.sleep(2000); // Use explicit waits in production code
                    }
                } catch (IOException | InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    driver.quit(); // Close the browser
                }
            }
        }
        

Program Explanation:

  1. Import Statements: Required classes for Selenium and Apache POI are imported.
  2. Main Method: Execution begins in the main method.
  3. WebDriver Setup: The ChromeDriver is configured, specifying the path to the driver executable.
  4. Navigating to the Page: The web application registration page is opened using driver.get().
  5. File Input Stream: The Excel file is read similarly to previous examples.
  6. Iterating Rows: A loop processes each row of the Excel file, extracting username, password, and email.
  7. Interacting with Web Elements: Selenium locates input fields using their IDs and fills them with the data from the Excel file.
  8. Form Submission: The registration form is submitted using click() on the register button.
  9. Wait for Processing: A temporary sleep is added to allow time for the registration to process; in production, use explicit waits instead.
  10. Cleanup: Finally, the browser is closed with driver.quit().

Selenium Script Execution with Command-Line Arguments

Selenium script execution with command-line arguments allows you to pass dynamic values such as URLs, browser types, or credentials to your test scripts without hardcoding them into the code. This approach is particularly useful for running tests in different environments or configurations, and it facilitates smooth integration with CI/CD tools like Jenkins.

Why Use Command-Line Arguments?

Using command-line arguments provides flexibility in test execution by allowing you to run the same script with different input values without modifying the script itself. It is especially helpful for the following scenarios:

Example 1: Passing URL as a Command-Line Argument

This example demonstrates how to pass the URL as a command-line argument while executing a Selenium script.


            public class SeleniumCommandLineExample {
                public static void main(String[] args) {
                    // Fetch URL from command-line argument
                    String url = args.length > 0 ? args[0] : "https://defaulturl.com";
                    System.setProperty("webdriver.chrome.driver", "./drivers/chromedriver.exe");
                    WebDriver driver = new ChromeDriver();
                    driver.get(url);
        
                    // Perform some basic actions (e.g., login)
                    // Example: driver.findElement(By.id("username")).sendKeys("testuser");
        
                    driver.quit();
                }
            }
            

To execute this script from the command line, you would use:


            java -cp .:selenium-server-standalone.jar SeleniumCommandLineExample https://shariqsp.com
            

Example 2: Passing Browser Type and URL

In this example, both the browser type and URL are passed as command-line arguments, enabling cross-browser testing with dynamic URLs.


            public class SeleniumCrossBrowserExample {
                public static void main(String[] args) {
                    String browserType = args.length > 0 ? args[0] : "chrome";
                    String url = args.length > 1 ? args[1] : "https://defaulturl.com";
                    
                    WebDriver driver;
        
                    // Set up browser based on command-line input
                    if (browserType.equalsIgnoreCase("firefox")) {
                        System.setProperty("webdriver.gecko.driver", "./drivers/geckodriver.exe");
                        driver = new FirefoxDriver();
                    } else {
                        System.setProperty("webdriver.chrome.driver", "./drivers/chromedriver.exe");
                        driver = new ChromeDriver();
                    }
        
                    // Launch the URL and perform actions
                    driver.get(url);
        
                    // Example: driver.findElement(By.id("username")).sendKeys("testuser");
        
                    driver.quit();
                }
            }
            

To execute this script from the command line, use:


            java -cp .:selenium-server-standalone.jar SeleniumCrossBrowserExample chrome https://shariqsp.com
            

Why Command-Line Arguments Are Useful in Jenkins

In Jenkins, you can configure your jobs to accept parameters dynamically, such as environment URLs, browser types, or credentials. By leveraging command-line arguments, Jenkins can pass these parameters to your Selenium tests, ensuring flexibility and reducing the need to modify test scripts for different environments or configurations.

Example: Running Selenium Tests with Command-Line Arguments in Jenkins

Here’s how you can configure a Jenkins job to pass parameters to your Selenium tests:


            # Example Jenkins build command
            java -cp .:selenium-server-standalone.jar SeleniumCrossBrowserExample ${BROWSER_TYPE} ${URL}
            

Example Setup in Jenkins:

This setup ensures that the same Selenium test can be executed across different browsers and environments without hardcoding the values inside the script, making it more adaptable for CI/CD pipelines.

Reading Data from XML Files in Selenium

XML (Extensible Markup Language) is commonly used for storing structured data, including test parameters, configurations, and credentials. In Selenium, you can read data from XML files using a test class approach, which integrates well with testing frameworks like TestNG.

Why Use XML for Data in Selenium?

Example XML File (`testdata.xml`)

The following XML file stores the test URL, username, and password:


            <testdata>
                <credentials>
                    <username>testuser</username>
                    <password>password123</password>
                </credentials>
                <environment>
                    <url>https://shariqsp.com</url>
                </environment>
            </testdata>
            

Reading XML Data in a Test Class (DOM Parser)

Here’s how you can read the XML data and integrate it into a Selenium test class using TestNG and Java's DOM parser:


            import org.openqa.selenium.By;
            import org.openqa.selenium.WebDriver;
            import org.openqa.selenium.chrome.ChromeDriver;
            import org.testng.annotations.AfterMethod;
            import org.testng.annotations.BeforeMethod;
            import org.testng.annotations.Test;
            import org.w3c.dom.*;
            import javax.xml.parsers.DocumentBuilder;
            import javax.xml.parsers.DocumentBuilderFactory;
            import java.io.File;
        
            public class SeleniumXMLTest {
        
                WebDriver driver;
                String username, password, url;
        
                @BeforeMethod
                public void setup() {
                    // Read XML data
                    readXMLData();
                    // Set up WebDriver
                    System.setProperty("webdriver.chrome.driver", "./drivers/chromedriver.exe");
                    driver = new ChromeDriver();
                }
        
                @Test
                public void loginTest() {
                    // Navigate to URL
                    driver.get(url);
                    // Perform login using data from XML
                    driver.findElement(By.id("username")).sendKeys(username);
                    driver.findElement(By.id("password")).sendKeys(password);
                    driver.findElement(By.id("loginButton")).click();
                }
        
                @AfterMethod
                public void teardown() {
                    driver.quit();
                }
        
                public void readXMLData() {
                    try {
                        // Load and parse XML file
                        File file = new File("./testdata.xml");
                        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                        DocumentBuilder builder = factory.newDocumentBuilder();
                        Document doc = builder.parse(file);
                        doc.getDocumentElement().normalize();
        
                        // Extract data from XML
                        username = doc.getElementsByTagName("username").item(0).getTextContent();
                        password = doc.getElementsByTagName("password").item(0).getTextContent();
                        url = doc.getElementsByTagName("url").item(0).getTextContent();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            

Explanation of the Test Class

Reading XML Data with XPath in Test Class

You can also use XPath for more precise data extraction from the XML file. Here’s how you can use XPath in the test class:


            import org.openqa.selenium.By;
            import org.openqa.selenium.WebDriver;
            import org.openqa.selenium.chrome.ChromeDriver;
            import org.testng.annotations.AfterMethod;
            import org.testng.annotations.BeforeMethod;
            import org.testng.annotations.Test;
            import org.w3c.dom.*;
            import javax.xml.parsers.DocumentBuilder;
            import javax.xml.parsers.DocumentBuilderFactory;
            import javax.xml.xpath.XPath;
            import javax.xml.xpath.XPathConstants;
            import javax.xml.xpath.XPathFactory;
            import java.io.File;
        
            public class SeleniumXPathXMLTest {
        
                WebDriver driver;
                String username, password, url;
        
                @BeforeMethod
                public void setup() {
                    // Read XML data with XPath
                    readXMLDataWithXPath();
                    // Set up WebDriver
                    System.setProperty("webdriver.chrome.driver", "./drivers/chromedriver.exe");
                    driver = new ChromeDriver();
                }
        
                @Test
                public void loginTest() {
                    // Navigate to URL
                    driver.get(url);
                    // Perform login using data from XML
                    driver.findElement(By.id("username")).sendKeys(username);
                    driver.findElement(By.id("password")).sendKeys(password);
                    driver.findElement(By.id("loginButton")).click();
                }
        
                @AfterMethod
                public void teardown() {
                    driver.quit();
                }
        
                public void readXMLDataWithXPath() {
                    try {
                        // Load and parse XML file
                        File file = new File("./testdata.xml");
                        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                        DocumentBuilder builder = factory.newDocumentBuilder();
                        Document doc = builder.parse(file);
                        doc.getDocumentElement().normalize();
        
                        // Use XPath to extract data
                        XPath xpath = XPathFactory.newInstance().newXPath();
                        username = (String) xpath.evaluate("/testdata/credentials/username", doc, XPathConstants.STRING);
                        password = (String) xpath.evaluate("/testdata/credentials/password", doc, XPathConstants.STRING);
                        url = (String) xpath.evaluate("/testdata/environment/url", doc, XPathConstants.STRING);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            

Benefits of Using XML in Selenium

Using `xmlTest` for Parameterization in Selenium with TestNG

TestNG’s `xmlTest` object allows you to pass parameters from the TestNG XML file directly to your test functions. This approach provides flexibility in managing dynamic data such as URLs, credentials, or other test configurations, without hardcoding them into the test script.

Why Use `xmlTest` for Parameterization?

Example: TestNG XML File with Parameters

The following TestNG XML file defines parameters (URL, username, and password) for the test execution:


            <?xml version="1.0" encoding="UTF-8"?>
            <suite name="TestSuite">
                <test name="LoginTest">
                    <parameter name="url" value="https://shariqsp.com"/>
                    <parameter name="username" value="testuser"/>
                    <parameter name="password" value="password123"/>
                    <classes>
                        <class name="com.test.SeleniumTestWithXmlTest"/>
                    </classes>
                </test>
            </suite>
            

In this example, the `url`, `username`, and `password` parameters are passed from the TestNG XML file to the test function using `xmlTest`.

Test Class: Using `xmlTest` for Parameterization

Here’s how you can access parameters using the `xmlTest` object in a Selenium test class:


            import org.openqa.selenium.By;
            import org.openqa.selenium.WebDriver;
            import org.openqa.selenium.chrome.ChromeDriver;
            import org.testng.ITestContext;
            import org.testng.annotations.AfterMethod;
            import org.testng.annotations.BeforeMethod;
            import org.testng.annotations.Test;
            import org.testng.xml.XmlTest;
        
            public class SeleniumTestWithXmlTest {
        
                WebDriver driver;
        
                @BeforeMethod
                public void setup(XmlTest xmlTest) {
                    // Fetch URL from the TestNG XML parameters using xmlTest
                    String url = xmlTest.getParameter("url");
                    System.setProperty("webdriver.chrome.driver", "./drivers/chromedriver.exe");
                    driver = new ChromeDriver();
                    driver.get(url);
                }
        
                @Test
                public void loginTest(XmlTest xmlTest) {
                    // Fetch username and password from the TestNG XML parameters using xmlTest
                    String username = xmlTest.getParameter("username");
                    String password = xmlTest.getParameter("password");
        
                    // Perform login
                    driver.findElement(By.id("username")).sendKeys(username);
                    driver.findElement(By.id("password")).sendKeys(password);
                    driver.findElement(By.id("loginButton")).click();
                }
        
                @AfterMethod
                public void teardown() {
                    driver.quit();
                }
            }
            

Explanation of the Test Class

How to Execute the Test

To run the above test using the TestNG XML file, execute the following command:


            java -cp .;testng.jar org.testng.TestNG testng.xml
            

Benefits of Using `xmlTest` for Parameterization

Using JDBC in Selenium Scripting

JDBC (Java Database Connectivity) is an API that enables Java applications to connect and interact with databases. In Selenium, JDBC can be used to interact with databases to perform data-driven testing. You can read data from a database and use it in your tests or validate database entries as part of the testing process.

Why Use JDBC in Selenium?

Scenario 1: Using JDBC to Fetch Data from a Database for Test Execution

In this scenario, you will fetch user credentials from a database and use them to log in to a web application using Selenium.

Database Table (`users`)


            +----+----------+--------------+
            | ID | Username | Password     |
            +----+----------+--------------+
            | 1  | testuser | password123  |
            | 2  | admin    | adminPass    |
            +----+----------+--------------+
            

Test Class: Fetching Data Using JDBC in Selenium


            import java.sql.Connection;
            import java.sql.DriverManager;
            import java.sql.ResultSet;
            import java.sql.Statement;
            import org.openqa.selenium.By;
            import org.openqa.selenium.WebDriver;
            import org.openqa.selenium.chrome.ChromeDriver;
            import org.testng.annotations.AfterMethod;
            import org.testng.annotations.BeforeMethod;
            import org.testng.annotations.Test;
        
            public class SeleniumJDBCExample {
        
                WebDriver driver;
                String dbURL = "jdbc:mysql://localhost:3306/testdb"; // Replace with your DB URL
                String username = "root";  // DB username
                String password = "root";  // DB password
        
                @BeforeMethod
                public void setup() {
                    System.setProperty("webdriver.chrome.driver", "./drivers/chromedriver.exe");
                    driver = new ChromeDriver();
                    driver.get("https://shariqsp.com/login");
                }
        
                @Test
                public void loginWithDBCredentials() {
                    try {
                        // Connect to the database
                        Connection connection = DriverManager.getConnection(dbURL, username, password);
                        Statement statement = connection.createStatement();
        
                        // Execute query to get the user credentials
                        String query = "SELECT Username, Password FROM users WHERE ID=1";
                        ResultSet resultSet = statement.executeQuery(query);
        
                        if (resultSet.next()) {
                            String dbUsername = resultSet.getString("Username");
                            String dbPassword = resultSet.getString("Password");
        
                            // Use the data from the database in the Selenium test
                            driver.findElement(By.id("username")).sendKeys(dbUsername);
                            driver.findElement(By.id("password")).sendKeys(dbPassword);
                            driver.findElement(By.id("loginButton")).click();
                        }
        
                        // Close the database connection
                        connection.close();
        
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
        
                @AfterMethod
                public void teardown() {
                    driver.quit();
                }
            }
            

Explanation

Scenario 2: Validating Database Entries After Performing Actions

In this scenario, you will create a new user through a web application and verify the user's entry in the database using JDBC.

Database Table (`users`)


            +----+----------+--------------+
            | ID | Username | Password     |
            +----+----------+--------------+
            | 1  | testuser | password123  |
            | 2  | admin    | adminPass    |
            | 3  | newuser  | newPass123   |  <-- New entry created by the test
            +----+----------+--------------+
            

Test Class: Validating Database After User Creation


            import java.sql.Connection;
            import java.sql.DriverManager;
            import java.sql.ResultSet;
            import java.sql.Statement;
            import org.openqa.selenium.By;
            import org.openqa.selenium.WebDriver;
            import org.openqa.selenium.chrome.ChromeDriver;
            import org.testng.Assert;
            import org.testng.annotations.AfterMethod;
            import org.testng.annotations.BeforeMethod;
            import org.testng.annotations.Test;
        
            public class SeleniumJDBCValidationExample {
        
                WebDriver driver;
                String dbURL = "jdbc:mysql://localhost:3306/testdb"; // Replace with your DB URL
                String username = "root";  // DB username
                String password = "root";  // DB password
        
                @BeforeMethod
                public void setup() {
                    System.setProperty("webdriver.chrome.driver", "./drivers/chromedriver.exe");
                    driver = new ChromeDriver();
                    driver.get("https://shariqsp.com/register");
                }
        
                @Test
                public void validateUserCreationInDB() {
                    String newUser = "newuser";
                    String newPass = "newPass123";
        
                    // Fill the registration form to create a new user
                    driver.findElement(By.id("username")).sendKeys(newUser);
                    driver.findElement(By.id("password")).sendKeys(newPass);
                    driver.findElement(By.id("registerButton")).click();
        
                    // Validate that the new user was created in the database
                    try {
                        // Connect to the database
                        Connection connection = DriverManager.getConnection(dbURL, username, password);
                        Statement statement = connection.createStatement();
        
                        // Execute query to verify the new user exists in the DB
                        String query = "SELECT Username FROM users WHERE Username='" + newUser + "'";
                        ResultSet resultSet = statement.executeQuery(query);
        
                        // Assert that the new user exists in the database
                        Assert.assertTrue(resultSet.next(), "User creation failed. User not found in database.");
        
                        // Close the database connection
                        connection.close();
        
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
        
                @AfterMethod
                public void teardown() {
                    driver.quit();
                }
            }
            

Explanation

Benefits of Using JDBC in Selenium Testing