QA-201 Sprint Summary

Modified on Thu, 11 Jul at 12:51 PM

Apache POI

What is Apache POI?

Apache POI (Poor Obfuscation Implementation) is a Java library for reading and writing Microsoft Office documents, including Excel files. It provides APIs to read, write, and modify various file formats including:

  • Excel (.xls, .xlsx)
  • Word (.doc, .docx)
  • PowerPoint (.ppt, .pptx)
  • Visio, Publisher, and Outlook

For Excel files, POI offers two main APIs:

  • HSSF (Horrible SpreadSheet Format) for .xls files
  • XSSF (XML SpreadSheet Format) for .xlsx files

How to read Data from Excel Files?

Using the apache.poi library we can read data from an Excel file's WorkSheets, handling both string and numeric cell types.

Example WorkSheet

Steps:

  1. Get Project Directory:

    System.getProperty("user.dir"); //returns the project directory path.
  2. Create File and FileInputStream: These objects are created to read the Excel file content into the program memory.

    File fileName = new File("path_to_excel_file"); 
    FileInputStream file = new FileInputStream(fileName);
  3. Create a Workbook object:

    XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream); //Creates a workbook object for the Excel file.
  4. Get the desired Sheet:

    XSSFSheet sheet = workbook.getSheet(sheetName);  //Gets the XSSFSheet object corresponding to a worksheet.
  5. Get Last Row Number:

    int rowsCount = sheet.getLastRowNum();  //Gets the 0-based index of the last row in the sheet.
  6. Get Row Object:

    XSSFRow row = sheet.getRow(rowIndex); //Gets the XSSFRow object corresponding to a row.
  7. Get Last Cell Number:

    int colsCount = sheet.getRow(1).getLastCellNum(); //Gets the 0-based index of the last column in the sheet.
  8. Get Cell Object:

    XSSFRow::getCell(colIndex); //Gets the XSSFCell object for a cell.
  9. Read cell values based on their type (string, numeric, etc.):

    XSSFCell cell = row.getCell(colIndex);
    switch (cell.getCellType()) {
        case STRING:
            System.out.print(cell.getStringCellValue());
            break;
        case NUMERIC:
            System.out.print(cell.getNumericCellValue());
            break;
        case BOOLEAN:
            System.out.print(cell.getBooleanCellValue());
            break;
    }
  10. Close the Workbook and FileInputStream:

    workbook.close();
    file.close();

Implementation:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.IOException;

public class ExcelReader {
    public static void main(String[] args) throws IOException {
        FileInputStream file = new FileInputStream("path/to/excel/file.xlsx");
        Workbook workbook = new XSSFWorkbook(file);
        Sheet sheet = workbook.getSheetAt(0);
        for (Row row : sheet) {
            for (Cell cell : row) {
                switch (cell.getCellType()) {
                    case STRING:
                        System.out.print(cell.getStringCellValue() + "\t");
                        break;
                    case NUMERIC:
                        System.out.print(cell.getNumericCellValue() + "\t");
                        break;
                }
            }
            System.out.println();
        }
        workbook.close();
        file.close();
    }
}

Note:

  • XSSFCell::getCellType(): Gets the cell type of the cell.

  • CellType.STRING: Use XSSFCell::getStringCellValue() to get the string value.

  • CellType.NUMERIC: Use XSSFCell::getNumericCellValue() to get the numeric value.

  • CellType.BOOLEAN: Use XSSFCell::getBooleanCellValue() to get the boolean value.

How to write Data to Excel Files ?

The apache.poi also allows us to create Excel files and writes a string to the first cell, and saves the file.

Steps:

  • Create a new Workbook:

    XSSFWorkbook workbook = new XSSFWorkbook(); //Creates a workbook object for an Excel file.
  • Create a new Sheet:

    XSSFSheet sheet = workbook.createSheet("Sheet Name"); //Creates a new sheet in the workbook.
  • Create Rows and Cells as needed:

    XSSFRow row = sheet.createRow(rowIndex); //Creates a new row
    XSSFCell cell = row.createCell(colIndex); //Creates a new cell.
  • Set cell values:

    cell.setCellValue("Data"); // Sets the value for a cell.
  • Write the Workbook to a FileOutputStream.

    FileOutputStream fileOut = new FileOutputStream("path/to/output/file.xlsx");
    workbook.write(fileOut);
  • Close the FileOutputStream and Workbook.

    fileOut.close();
    workbook.close();

Implementation:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;

public class ExcelWriter {
    public static void main(String[] args) throws IOException {
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("Sample Sheet");
        Row row = sheet.createRow(0);
        Cell cell = row.createCell(0);
        cell.setCellValue("Hello, Apache POI!");

        FileOutputStream fileOut = new FileOutputStream("path/to/output/file.xlsx");
        workbook.write(fileOut);
        fileOut.close();
        workbook.close();
    }
}

Design Patterns

What are Design Patterns?

Design patterns are typical solutions to common problems in software design. They provide tried-and-tested structures to solve recurring design issues, akin to blueprints in architecture. These patterns are not finished code but initial structures to kickstart development, making projects simpler and easier to maintain as they grow. 

Importance of Design Patterns

Design patterns represent the best practices used by experienced object-oriented software developers. These solutions were developed over time through trial and error. 

Advantages:

  • Reusability: Applicable across multiple projects.

  • Clarity: Enhance system architecture and facilitate building better systems.

  • Maintainability: Simplify project maintenance as it scales.

Design Patterns in Software Development

Creational Design Patterns

Creational design patterns focus on the efficient creation of objects.


Types

  • Factory
  • Purpose: Returns a specific subclass object based on input.

  • Analogy: In an ice cream factory, the client selects the type of ice cream without needing to know how it is made.

  • Singleton
  • Purpose: Ensures only one instance of a class is created throughout the program.

  • Analogy: A country can only have one government; creating additional governments is prohibited.


Structural Design Patterns

Structural design patterns focus on class and object composition to form larger structures. 

Types

  • Facade
  • Purpose: Restricts exposure to complex underlying structures using a simplified interface.

  • Analogy: In a restaurant, the waiter takes your order and you only wait for the food. The kitchen operations are hidden from you.

  • Adapter
  • Purpose: Allows two incompatible interfaces to work together.

  • Analogy: While traveling, an adapter lets you charge your phone with any plug type in a foreign country.


Behavioural Design Patterns


Behavioral design patterns focus on communication between objects and classes.

Types

  • Strategy
    • Purpose: Allows the client to choose an implementation from multiple algorithms.

    • Analogy: To reach a location on a map, you can choose different modes of transportation or routes.

  • Observer
    • Purpose: Defines a one-to-many relationship between objects.

    • Analogy: A newspaper publisher (subject) notifies subscribers (observers) whenever a new edition is published.

Design Patterns in Selenium/Test Automation

Page Object Model (POM)

Stores elements and actions for a page in a single class. Improves test case maintenance and reduces code duplication.

Without Page Object Model


With Page Object Model



  • For each webpage, we have a class file which contains webElements and methods related to the webpage.

  • Test cases utilize these class files to get the elements instead of directly accessing them.

  • Reduces code duplication and improves test case maintenance.



Example Implementation:

public class LoginPage {
    private WebDriver driver;
    @FindBy(id = "username")
    private WebElement username;

    @FindBy(id = "password")
    private WebElement password;

    @FindBy(id = "login")
    private WebElement loginButton;

    public LoginPage(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
    }

    public void login(String user, String pass) {
        username.sendKeys(user);
        password.sendKeys(pass);
        loginButton.click();
    }
}

Encapsulates web page elements and actions for a specific page within a class. 

Factory Design Pattern

Creates objects based on input, useful for generating test data or driver instances. 

Example Implementation:

public interface WebDriverFactory {
    WebDriver createWebDriver();
}

public class ChromeDriverFactory implements WebDriverFactory {
    public WebDriver createWebDriver() {
        return new ChromeDriver();
    }
}

public class FirefoxDriverFactory implements WebDriverFactory {
    public WebDriver createWebDriver() {
        return new FirefoxDriver();
    }
}   


Facade Design Pattern

Provides a simplified interface to complex subsystems, enhancing test script readability. 

Example Implementation:

public class ComplexSystem {
    public void operation1() { System.out.println("Operation 1"); }
    public void operation2() { System.out.println("Operation 2"); }
}

public class Facade {
    private ComplexSystem system = new ComplexSystem();

    public void simpleOperation() {
        system.operation1();
        system.operation2();
    }
}   


Singleton Pattern

Ensures a single instance of a class, such as a WebDriver, to avoid multiple initializations and enhance test performance. 

Example Implementation:

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
    


Anti-Patterns

Anti-patterns are commonly used patterns in software design that lead to negative consequences. Unlike design patterns, which are best practices, anti-patterns result in poor design choices and problematic code. 

Example of an Anti-Pattern

Anti-Pattern:

public void create_main_window(){
    Window window = new Window(600, 600)
}
Consequences: 
Hardcoding values directly in the function lacks flexibility and maintainability.

Design Pattern:

public void create_main_window(int height, int width){
    Window window = new Window(height, width)
}
Benefits: 
This approach enhances flexibility, making the code easier to maintain and adapt.


Page Factory

Page Factory in Selenium is a way to create object repositories for web elements on a page, offering an alternative syntax and semantics for managing web elements. It uses lazy initialization to identify elements only when they are used, enhancing performance and efficiency. 

Page Factory simplifies the creation of object repositories for web elements using annotations and lazy initialization. 

Key Components

  • Lazy Loading: Initializes web elements only when they are accessed, improving performance. 

    PageFactory.initElements(driver, this);
    AjaxElementLocatorFactory factory = new AjaxElementLocatorFactory(driver, 10);
    PageFactory.initElements(factory, this);
  • Annotations

    • @FindBy Annotation: Locates web elements using different strategies. 

      @FindBy(id = "userName")
      WebElement username;
  •  @FindBys (AND condition): Locates web elements using multiple criteria that all must match. 

    @FindBys({
        @FindBy(class = "custom-control-check-box"),
        @FindBy(id = "game-chk-box")
    })
    WebElement chkBox;
  •  @FindAll (OR condition): Locates web elements using multiple criteria, with at least one matching. 

    @FindAll({
        @FindBy(id = "btn"),
        @FindBy(name = "sbmtBtn"),
        @FindBy(class = "btn-primary")
    })
    WebElement submitBtn;
  •  @CacheLookUp: Caches elements for faster access when used multiple times. 

    @CacheLookUp
    @FindBy(id = "login")
    WebElement loginButton;  


Differences Between Page Object Model and Page Factory

  • Page Object Model: A design pattern for managing web elements.

    • Initialization: Manual.

    • Lazy Initialization: Not provided.

  • Page Factory: A class that implements the Page Object Model pattern.

    • Initialization: Uses @FindBy and initElements().

    • Lazy Initialization: Provided.

Data Providers

Data providers allow passing values to test functions from external sources, such as Excel sheets using Apache POI, instead of hardcoding data.

  1. Create a Data Provider Method:

    • Annotate a method with @DataProvider.

    • The method should return a two-dimensional array or an Iterator of test data.

@DataProvider
public Object[][] testData() {
    return new Object[][] {
        {"username1", "password1"},
        {"username2", "password2"},
        {"username3", "password3"}
    };
}
  1. Use the Data Provider in Test Methods:

    • Annotate the test method with @Test(dataProvider = "dataProviderName").

    • The test method should accept parameters matching the data provider's output.

@Test(dataProvider = "testData")
public void testLogin(String username, String password) {
    // Test steps for login using the provided username and password
}


Wrapper Methods

Wrapper methods in Selenium encapsulate commonly used actions and verifications, simplifying code and enhancing maintainability.

Key Concepts

  • Wrapper Methods:

    • Encapsulate actions such as finding elements, clicking, and entering text, providing additional functionality like logging or retries.

  • Wrapper Classes for Primitive Data Types:

    • Provide methods to store, manipulate, or convert data beyond simple storage capabilities.

  • Function Overriding vs. Wrapper Methods:

    • Function Overriding: Replaces the parent class method with a new method in the child class.

    • Wrapper Methods: Create new methods that wrap existing methods, adding extra functionality without replacing the original method.

Advantages

We can implement features/enhancements for a specific action as and when needed, like

  • Retry Mechanism:

    • To handle flaky tests by retrying actions like clicks.

  • Alternative Locators:

    • To find elements using different locators if the primary one fails.

  • Exception Handling:

    • To manage unexpected scenarios, such as elements becoming obscured or requiring scrolling.

  • Enhanced Assertions:

    • To capture additional information like screenshots on assertion failures.

Example Implementations

  • Locate and click

public void clickElement(By locator) {
    driver.findElement(locator).click();
}
  • Log out character count, type the text, and print the inner HTML of the element.

public static void advancedSendKeys(By locator, String text) {
    WebElement e = driver.findElement(locator);
    System.out.println("Number of characters: " + text.length());
    e.sendKeys(text);
    System.out.println("Inner HTML: " + e.getAttribute("innerHTML"));
}

Example Usages

@Test
public void searchTest() {
    Wrapper wrapper = new Wrapper(driver);
    wrapper.advancedSendKeys(By.id("searchButton"), "Youtube");
    wrapper.clickElement(By.id("searchIcon"));
}


Customizing Extent Reports with Screenshots

Extent Report is an open-source reporting library used in test automation, easily integrated with major testing frameworks like TestNG, JUnit, and NUnit. It generates customizable HTML reports with stepwise representation, pie charts, execution time, and screenshot capabilities.

Screenshots in Reports

Capturing screenshots in test reports helps identify issues when tests fail. Screenshots can be added using:

  • Setup Extent Reports: Initialize ExtentReports and ExtentTest in your test class.

  • Capture and Log Screenshots: Use a method to capture screenshots and log them in the report when a test fails.

Example Implementation

import com.relevantcodes.extentreports.ExtentReports;
import com.relevantcodes.extentreports.ExtentTest;
import com.relevantcodes.extentreports.LogStatus;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;

import java.io.File;
import java.io.IOException;

public class ExtentReportsDemo {
    ExtentReports reports = new ExtentReports("path/to/report.html", true);
    ExtentTest test = reports.startTest("TestName");

    public static String capture(WebDriver driver) throws IOException {
        File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
        File dest = new File(System.getProperty("user.dir") + "/screenshots/" + System.currentTimeMillis() + ".png");
        String filePath = dest.getAbsolutePath();
        FileUtils.copyFile(scrFile, dest);
        return filePath;
    }

    public void logFailureWithScreenshot(WebDriver driver) throws IOException {
        String screenshotPath = capture(driver);
        test.log(LogStatus.FAIL, test.addScreenCapture(screenshotPath) + "Test Failed");
    }

    // Other test methods 
}

This captures a screenshot and logs it in the Extent Report when a test fails.


Jenkins

Jenkins is an open-source automation server used for continuous integration and continuous delivery (CI/CD). It automates the build, test, and deployment processes. In Jenkins, we can create pipelines and jobs to manage and automate tasks effectively.

Key Concepts:

  • Jenkins Server: The master node that hosts the web application. It manages the jobs and tasks to be executed.

  • Jenkins Agent: Nodes that run the actual tasks, connected to the server via TCP/IP or WebSocket.

  • Executors: Processes on agents that run tasks in parallel.

  • Jenkins Job: Specific tasks configured to run on a schedule or triggered by events.

Core Features:

  • Source Code Management (SCM): Integrates with version control systems like Git, Subversion, and Mercurial.

  • Build Triggers: Executes jobs based on schedules, code changes, or other job completions.

  • Build Steps: Actions performed during a build, such as running scripts, tests, or deploying code.

  • Build Environment: Configures the environment, specifying OS, tools, and libraries.

  • Post-Build Actions: Additional tasks after a build, like notifications or triggering other jobs.

  • Build History and Reports: Provides logs, trends, and test results for builds.

  • Parameters: Input arguments for jobs, used in different job steps or stages.

Advantages:

  • Automation: Reduces manual intervention in build and deployment processes.

  • Scalability: Handles large volumes of tests and builds efficiently.

  • Customizability: Extensive plugin ecosystem allows integration with various tools and services.

  • Continuous Integration: Automatically building and testing code on every commit to ensure early detection of issues.

  • Continuous Delivery: Extending CI to automate deployment to various environments.

  • Parallel Testing: Running tests in parallel on multiple agents to save time.

Common Jenkins Tasks:

  • Setting up Pipelines: Automating workflows from code commit to deployment.

  • Monitoring Builds: Tracking the status and history of builds.

  • Managing Jobs: Configuring and scheduling tasks to run automatically.

Jenkins Job:

A Jenkins job is a task or set of tasks that Jenkins executes, which can be scheduled or triggered by events like code commits. It is crucial for continuous integration and delivery (CI/CD).

Components of a Jenkins Job:

  • Source Code Management (SCM):

    • Integrates with version control systems (e.g., Git, Subversion).

    • Specifies the repository and branch to build.

  • Build Triggers:

    • Schedules job execution.

    • Triggers include scheduled builds, code repository changes, or job completions.

  • Build Steps:

    • Defines actions during a build (e.g., running tests, deploying code).

  • Build Environment:

    • Configures the environment (OS, tools, libraries) for the build.

  • Post-Build Actions:

    • Tasks after build completion (e.g., sending notifications, archiving artifacts).

  • Build History and Reports:

    • Provides logs, build trends, and test results.

  • Parameters:

    • Input arguments used in various job stages.

Types of Jenkins Jobs:

  • Freestyle Project:

    • Simple and flexible.

    • Allows configuration of SCM, build triggers, build steps, and post-build actions.

  • Pipeline Project:

    • Suitable for defining complex build processes.

    • Uses a script (typically written in Groovy) to define the entire build process.

  • Multi-Configuration Project:

    • Ideal for running the same build with different configurations.

    • Used for testing against multiple environments or configurations.

  • Folder:

    • Organizes multiple jobs into a single folder.

    • Useful for managing a large number of jobs.

  • Multibranch Pipeline:

    • Automatically creates pipelines for each branch in a repository.

    • Efficient for managing multiple branches in a CI/CD pipeline.

Configuring a Job

  • Login to Jenkins and Create a New Job:

    • Access Jenkins using your credentials.

    • Click on the "New Item" option on the left side.

  • Enter the job name and select the job type (e.g., Freestyle project).

  • Add Job Description: Provide a meaningful description for the job.

  • Add Parameters: Add parameters such as the repository URL to the job.

  • Add Build Steps:

    • First Build Step:

  • Second Build Step:

    echo "Step #2 Test.." 
    echo "Starting Automation Run"
    echo "Gradle test"
    echo "Test successful"


  • Third Build Step:

    echo "Step #3 Deploy.." 
    echo "Deploying Codebase to production" 
    echo "Deployment completed successfully"


  • Add Post-Build Actions:

    • Click on the option to add a post-build step.

    • Enter your email address to send email notifications

  • Save the Job:

    • Save the configuration.

  • Execute the Job:

    • Use the "Build with Parameters" option to run the job.


Happy Learning!

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article