Automation QA Testing Course Content

ExtentReports in Selenium


Why do we need reporting?

Status to:
                1)Upper Management
                2)Development Team
                3)Product/Project Management
1)Representation of automation efforts outside of the team

2- Using reports we calculate the time taken by each test case that helps to calculate ROI(Return on Investment).

3- You can share automation reports with your team and clients as well to share the status of testing progress etc.

What goes in Reports?
        1)High level status of automation run
        2)Should clearly represent the Test Suite/Test Class
        3)Name of Test Classes, Test Methods
        4)Status of Test Methods (Success/Failed/Skipped)
        5)No need to put exception messages/other details of debugging

Why Extent Reports?
      1) Beautiful-looking reports
        2)Automation Framework Independent
        3) Easy-to-use APIs
        4)Provides a dashboard for the entire run
        5)Attach Screenshots
        6)Customizable
For More Information on extent reports refer linkExtentReportDocumentation

------------------------------------------------------------------------------------------------------------------
ExtentMnager.Java

package com.qa.linkedin.listeners;
import java.io.File;
import java.util.Date;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.reporter.ExtentHtmlReporter;
import com.aventstack.extentreports.reporter.configuration.Theme;
import com.qa.linkedin.util.Constants;
import com.qa.linkedin.util.TestUtil;


public class ExtentManager {
  private static final Logger log = LogManager.getLogger(ExtentManager.class.getName());
    private static ExtentReports extent;

    public static ExtentReports getInstance() {
        if (extent == null) {
            createInstance();
        }
        return extent;
    }
public static synchronized ExtentReports createInstance() {
        String fileName = TestUtil.getReportName();
        String reportsDirectory = Constants.REPORTS_DIRECTORY;
        new File(reportsDirectory).mkdirs();
        String path = reportsDirectory + fileName;
        log.info("*********** Report Path ***********");
        log.info(path);
        log.info("*********** Report Path ***********");
        ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(path);    htmlReporter.config().setTheme(Theme.STANDARD);
    htmlReporter.config().setDocumentTitle("Linkedin Automation Test Run");
    htmlReporter.config().setEncoding("utf-8");
    htmlReporter.config().setReportName(fileName);
    extent = new ExtentReports();
    extent.setSystemInfo("Organization", "RameshQaAutomationPlatform");
    extent.setSystemInfo("Automation Framework", "Selenium Webdriver");
    extent.setSystemInfo("Automation Tester", "Ramesh");
    extent.setSystemInfo("Build no", "QA-1234");
    extent.attachReporter(htmlReporter);
    
    return extent;
}

}
=================================================
ExtentReportListener:
----------------------------------------------------------------------------
package com.qa.linkedin.listeners;
import java.io.IOException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.WebDriver;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestNGMethod;
import org.testng.ITestResult;
import org.testng.Reporter;
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.MediaEntityBuilder;
import com.aventstack.extentreports.Status;
import com.aventstack.extentreports.markuputils.ExtentColor;
import com.aventstack.extentreports.markuputils.Markup;
import com.aventstack.extentreports.markuputils.MarkupHelper;
import com.qa.linkedin.base.TestBase;
import com.qa.linkedin.base.WebDriverFactory;
import com.qa.linkedin.util.BasePageWebActions;
import com.qa.linkedin.util.TestUtil;

public class ExtentReportListener extends TestBase implements ITestListener {
    private static ExtentReports extentReports = ExtentManager.getInstance();
    private static ThreadLocal<ExtentTest> extentTest = new ThreadLocal<ExtentTest>();
    private static final Logger log = LogManager.getLogger(ExtentReportListener.class.getName());

    /**
     * Invoked after the test class is instantiated and before
     * any configuration method is called.
     *
     * @param context
     */
    public void onStart(ITestContext context) {
        log.info("onStart -> Test Tag Name: " + context.getName());
        ITestNGMethod methods[] = context.getAllTestMethods();
        log.info("These methods will be executed in this <test> tag");
        for (ITestNGMethod method: methods) {
            log.info(method.getMethodName());
        }
    }

    /**
     * Invoked after all the tests have run and all their
     * Configuration methods have been called.
     *
     * @param context
     */
    public void onFinish(ITestContext context) {
        log.info("onFinish -> Test Tag Name: " + context.getName());
        extentReports.flush();
    }
    /**
     * Invoked each time before a test method will be invoked.
     *
     * @param result
     * @see ITestResult#STARTED
     */
    public void onTestStart(ITestResult result) {
        ExtentTest test = extentReports.createTest(result.getInstanceName() + " :: "
                + result.getMethod().getMethodName());
        extentTest.set(test);
    }

    /**
     * Invoked each time a test method succeeds.
     *
     * @param result
     * @see ITestResult#SUCCESS
     */
    public void onTestSuccess(ITestResult result) {
        log.info("onTestSuccess -> Test Method Name: " + result.getName());
        String methodName = result.getMethod().getMethodName();
        String logText = "<b>" + "Test Method " + methodName + " Successful" + "</b>";
        Markup m = MarkupHelper.createLabel(logText, ExtentColor.GREEN);
        extentTest.get().log(Status.PASS, m);
    }

    /**
     * Invoked each time a test method fails.
     *
     * @param result
     * @see ITestResult#FAILURE
     */
    public void onTestFailure(ITestResult result) {
        log.info("onTestFailure -> Test Method Name: " + result.getName());
        String methodName = result.getMethod().getMethodName();
        String exceptionMessage = Arrays.toString(result.getThrowable().getStackTrace());
        extentTest.get().fail("<details>" + "<summary>" + "<b>" + "<font color=red>" +
                "Exception Occurred: Click to see details: " + "</font>" + "</b>" + "</summary>" +
        exceptionMessage.replaceAll(",", "<br>") + "</details>" + " \n");

        String browser = WebDriverFactory.getInstance().getBrowser();
        WebDriver driver = WebDriverFactory.getInstance().getDriver(browser);
        BasePageWebActions cd = new BasePageWebActions();
        String path = cd.takeScreenshot(result.getName(), browser);
        try {
            extentTest.get().fail("<b>" + "<font color=red>" +
                    "Screenshot of failure" + "</font>" + "</b>",
                    MediaEntityBuilder.createScreenCaptureFromPath(path).build());
        } catch (IOException e) {
            extentTest.get().fail("Test Method Failed, cannot attach screenshot");
        }

        String logText = "<b>" + "Test Method " + methodName + " Failed" + "</b>";
        Markup m = MarkupHelper.createLabel(logText, ExtentColor.RED);
        extentTest.get().log(Status.FAIL, m);
    }

    /**
     * Invoked each time a test method is skipped.
     *
     * @param result
     * @see ITestResult#SKIP
     */
    public void onTestSkipped(ITestResult result) {
        log.info("onTestSkipped -> Test Method Name: " + result.getName());
        String methodName = result.getMethod().getMethodName();
        String logText = "<b>" + "Test Method " + methodName + " Skipped" + "</b>";
        Markup m = MarkupHelper.createLabel(logText, ExtentColor.YELLOW);
        extentTest.get().log(Status.PASS, m);
    }

    /**
     * Invoked each time a method fails but has been annotated with
     * successPercentage and this failure still keeps it within the
     * success percentage requested.
     *
     * @param result <code>ITestResult</code> containing information about the run test
     * @see ITestResult#SUCCESS_PERCENTAGE_FAILURE
     */
    public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
        // Ignore this
    }
}
-------------------------------------------------------------------

AutoIt Tool Usage


                                 AutoIt


Ø  Mouse Over on AUTOIT menu


Ø  Click on Downloads menu option

Ø  Click on Download AutoIt button


Ø  Mouse Over on AUTOIT EDITOR Menu

Ø  Click on Editor Downloads option
Ø  Click on Below Exe file

After downloading the AutoIt and AutoIt Editor
Click on each setup files & Complete the installation

Click on Next button

Keep the default installation location & Click on Install button


Click on Second SciTEAutoIt exe file and complete the installation process

GO to Help Section & Click on Index


We are going to use three commands
1)ControlFocus():


2)ControlSetText():

3)ControlClick():


Launch the AutoIt Editor & Identifier Tool From c:/program files (x.86)/AutoIt


Launch by clicking on AutoItInfo to open Identifier Tool

GO to C:/program files x 86/AutoIt/SciTE àClick on SciTE àEditor will lanuch


SCITE editor will launch



Click on Upload/browse icons in your application àThen window will open



Identify the File name field with Finder Toolàit will give title, class and instance values of the file name editbox





Identify the Open button


Script is ready now


Save the above file  --Go to File MenuàSave As


Save in one Folder AutoIt in Desired location


Right Click on FileàCompile the Script


After Compilation we will get one more application file


Write the selenium code and give the autoit script path using RunTime class getRuntime().exec(“path of the AutoItScript”)

 RunTime.getRunTime().exe("C:\\AutoItScript\\FileUploadFirefox.exe");

if you want to run on chrome generate new AutoItScript and compile then give that exe file path
 Runtime.getRuntime().exec("C:\\AutoItScript\\FileUploadchrome.exe");

-----------------------------------------------------------------------------------------------------------------
Step1)
AutoItScript for Chrome
copy and past below code in notepad
save filename:: AutoitScriptForChrome.au3
Select Save As option: All Types
----------------------------------------------------------------------------------------------------------------
WinWait("Open","",1000);
ControlFocus("Open","","Edit1");
ControlSetText("Open","","Edit1","C:\Users\rames\Downloads\Ramesh-stateID.pdf");
WinWait("Open","",1000);
ControlClick("Open","","Button1");

-----------------------------------------------------------------------------------------------------------------------
AutoItScript for Firefox
Copy and paste the below code in notepad
and save the filename:: AutoitScriptForFirefox.au3
Select Save As an option: All Types
------------------------------------------------------------------------------------------------------
WinWait("File Upload","",1000);
ControlFocus("File Upload","","Edit1");
ControlSetText("File Upload","","Edit1","C:\Users\rames\Downloads\Ramesh-stateID.pdf");
WinWait("File Upload","",1000);
ControlClick("File Upload","","Button1");
-------------------------------------------------------------------------------------------------------------
Step2:
Convert the filename.au3 as a .exe file 
right click on the filename.au3 -->select compile Script(x64)-->this will generate the AutoitScriptForFirefox.exe/AutoitScriptForChrome.exe
===================================================================
Step3: write an Automation script for uploading files

AutoIt Upload Files Programs:
package testngprograms;

package testngprograms;

import org.testng.annotations.Test;

import basicprograms.WebDriverUtils;

import org.testng.annotations.BeforeClass;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;

import java.io.IOException;
import java.time.Duration;
import java.util.LinkedList;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import org.testng.Reporter;


public class FileUploadUsingAutoIt {
WebDriver driver = null;
WebDriverWait wait = null;
WebDriverUtils wutils = null;
//String fpath = "C:\\Users\\rames\\Downloads\\How to access Workday.pdf";
@Parameters({ "browser" })
@Test
public void fileUploadByAutoItTest(String browser) throws InterruptedException, IOException {
Reporter.log("open the url:https://easyupload.io/", true);
driver.get("https://easyupload.io/");
Reporter.log("verify the page title Easyupload.io - Upload files for free and transfer big files easily.", true);
wait.until(ExpectedConditions.titleContains("Easyupload.io - Upload files for free and transfer big files easily."));
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > main > div > div.upload > h1")));
String headerTxt = driver.findElement(By.cssSelector("body > main > div > div.upload > h1")).getText();
Assert.assertEquals("Upload and share files for free", headerTxt);
Reporter.log("click on cclick here or drop files to upload button", true);
driver.findElement(By.xpath("//*[@id='dropzone']/div[2]/button")).click();
Reporter.log("call the robotclass method to handle uplaod file", true);
//
if(browser.equalsIgnoreCase("chrome")) {
Runtime.getRuntime().exec("C:\\Users\\rames\\OneDrive\\Documents\\AutoitScript\\AutoItScriptForChrome.exe");
}else if(browser.equalsIgnoreCase("firefox")) {
Runtime.getRuntime().exec("C:\\Users\\rames\\OneDrive\\Documents\\AutoitScript\\AutoItScriptForFirefox.exe");
}
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("upload")));
Thread.sleep(1000);
Reporter.log("click on Upload button", true);
driver.findElement(By.id("upload")).click();
Reporter.log("File uploaded message assertions", true);
wait.until(ExpectedConditions.presenceOfElementLocated(By.className("upload-success")));
Assert.assertTrue(driver.findElement(By.xpath("//div[@class='upload-success']/h5")).isDisplayed(), "file is not uploaded");
Assert.assertEquals("Your file has been uploaded successfully.",driver.findElement(By.xpath("//div[@class='upload-success']/h5")).getText());
Thread.sleep(2000);
}
@Parameters({ "browser" })
@BeforeClass(alwaysRun = true)
public void beforeClass(String browser) {
if (browser.equalsIgnoreCase("chrome")) {
ChromeOptions opt = new ChromeOptions();
opt.setAcceptInsecureCerts(true);
driver = new ChromeDriver(opt);
Reporter.log("chromebrowser is launched", true);
} else if (browser.equalsIgnoreCase("firefox")) {

FirefoxOptions opt = new FirefoxOptions();
opt.setAcceptInsecureCerts(true);
// opt.setBinary("C:\\Program Files\\Mozilla Firefox\\firefox.exe");
// interface refvar=new implementedclass();
driver = new FirefoxDriver(opt);
Reporter.log("firefox browser is launched", true);
} else if (browser.equalsIgnoreCase("edge")) {
EdgeOptions opt = new EdgeOptions();
opt.setAcceptInsecureCerts(true);
driver = new EdgeDriver(opt);
Reporter.log("edge browser is launched", true);
}
Reporter.log("maximize the window", true);
driver.manage().window().maximize();
Reporter.log("add implicitwait", true);
driver.manage().timeouts().implicitlyWait(Duration.ofMillis(10000));
Reporter.log("add explicitwait object", true);
wait = new WebDriverWait(driver, Duration.ofSeconds(30));
Reporter.log("creating Object for WebDriverUtils class", true);
wutils = new WebDriverUtils(driver);
}

@AfterClass
public void afterClass() {
System.out.println("I am in AfterClass block");
// close the browser
driver.close();
}

}
--------------------------------------------------------------------
ActionsTestNG.xml file format
---------------------------------------------------------------

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="ActionsSuite">
  <test thread-count="5" name="ActionsTest">
  <parameter name="browser" value="firefox"></parameter>
    <classes>
      <!-- class name="testngprograms.DragAndDropTest"/ -->
      <!-- class name="testngprograms.DragAndDropByTest"></class -->
      <!-- class name="testngprograms.FlipKartMenuHandlingTest"></class -->
      <!-- class name="testngprograms.ActionsMethodsDemo"></class -->
      <!-- class name="testngprograms.OpenLinkNewTabAndNewWindowTest"></class -->
      <!-- class name="testngprograms.HandlingWebTableTest"></class -->
      <!-- class name="testngprograms.JqueryDatePickerTest"></class -->
      <!-- class name="testngprograms.FileUploadUsingRobot"></class -->
      <class name="testngprograms.FileUploadUsingAutoIt"></class>
    </classes>
  </test> <!-- ActionsTest -->
</suite> <!-- ActionsSuite -->
-----------------------------------------------------





Hybrid Framework


FrameWork: it is set of instructions and guidelines will be followed and arrange the code in proper folder structure.

FrameWork Features:

1)reusability of the Code
2)Maintenance of code is very eay
3)It provides the Reports
4)It provides the logs and screenshots
5)any non technical/novice resources can understand the code easily

Differenet FrameWorks:

1)DataDriven Framework
2)keyword driven framework
3)Hybrid Framework
4)BDD
===========================================================
What is the difference in keyword driven vs data driven vs behavior driven frameworks?
Keyword-driven, data-driven, and behavior-driven testing frameworks are all strategies used in software testing, each with its own approach and focus. Here's a comparison of these three testing frameworks:

Keyword-Driven Testing Framework:

  • Focus: Keyword-driven testing, also known as table-driven testing, focuses on separating test automation logic from test data and test scripts.
  • Components:
    • Keywords: Actions or operations that represent test steps (e.g., "click," "type," "verify").
    • Test Data: Input and expected output data.
    • Test Scripts: A set of instructions that use keywords and test data to execute test cases.
  • Advantages:
    • Promotes reusability of keywords.
    • Easy to maintain as test data and logic are separated.
    • Non-technical team members can write and understand test cases.
  • Example: A keyword-driven framework might have keywords like "login," "search," and "add to cart," which are combined with test data to create test scripts.

Data-Driven Testing Framework:

  • Focus: Data-driven testing focuses on testing the same functionality with multiple sets of data to ensure the application behaves correctly across various inputs.
  • Components:
    • Test Data: Multiple sets of input and expected output data.
    • Test Scripts: A single set of test scripts that can iterate over different sets of test data.
  • Advantages:
    • Efficient for testing multiple scenarios with minimal test script duplication.
    • Easily extends test coverage by adding new data sets.
  • Example: In a data-driven framework, you might have a single login test script that is executed with different username and password combinations from a data source (e.g., spreadsheet or database).

Behavior-Driven Testing Framework (BDD):

  • Focus: Behavior-driven testing focuses on describing the expected behavior of an application in natural language terms, making it more accessible to non-technical stakeholders.
  • Components:
    • Feature Files: Text files written in a structured language (e.g., Gherkin) that describe features, scenarios, and steps.
    • Step Definitions: Code that maps the steps in feature files to automation logic.
  • Advantages:
    • Encourages collaboration between technical and non-technical team members.
    • Provides a clear understanding of the expected behavior of the application.
    • Promotes test automation using a human-readable format.
  • Example: In a BDD framework, you might have a feature file that describes a user registration feature with scenarios like "Register with valid credentials" and "Register with invalid credentials."
  • In summary, these testing frameworks differ in their approach and focus:

    • Keyword-Driven Framework focuses on reusability and separating test logic from data.
    • Data-Driven Framework focuses on testing the same functionality with different sets of data.
    • Behavior-Driven Framework (BDD) focuses on describing expected behavior using natural language and encourages collaboration between technical and non-technical team members.

    The choice of framework depends on your project's requirements, the team's expertise, and the level of collaboration needed between technical and non-technical stakeholders. Some projects may even combine elements from multiple frameworks to create a custom solution that best fits their needs.

=====================================================
HybridFramework:
 It is combination of TestNG+Datadriven/KeywordDriven and Page Object Model Design Pattern.

TestNg is used to design the TestCases

Datadriven is used to test the same scenario with multiple sets of data

POM: how you we can design our page Elements/Objects

What is Page Object Model in Selenium?

Page Object Model, also known as POM, is a design pattern in Selenium that creates an object repository for storing all web elements. It is useful in reducing code duplication and improves test case maintenance.

In Page Object Model, consider each web page of an application as a class file. Each class file will contain only corresponding web page elements. Using these elements, testers can perform operations on the website under test

Advantages of Page Object Model
  • Helps with easy maintenance: POM is useful when there is a change in a UI element or there is a change in an action. An example would be: a drop-down menu is changed to a radio button. In this case, POM helps to identify the page or screen to be modified. As every screen will have different java files, this identification is necessary to make the required changes in the right files. This makes test cases easy to maintain and reduces errors.
  • Helps with reusing code: As already discussed, all screens are independent. By using POM, one can use the test code for one screen, and reuse it in another test case. There is no need to rewrite code, thus saving time and effort.
  • Readability and Reliability of scripts: When all screens have independent java files, one can easily identify actions that will be performed on a particular screen by navigating through the java file. If a change must be made to a certain section of code, it can be efficiently done without affecting other files.

Implementing POM in Selenium Project


1)Plain page object model

public static final By elementname=By.locator("locator");

Respective methods developed for above elements like doing actions on the elements, verifying whether that element is present in that page or not, page title is present or not. This is all developed using webdriver methods

to do action you have to write syntax :
public void clickElement(){
driver.findElement(elementname).click();
}

2)Using PageFactory class

What is Page Factory in Selenium?

Page Factory is a class provided by Selenium WebDriver to support Page Object Design patterns. In Page Factory, testers use @FindBy annotation. The initElements method is used to initialize web elements.

  • @FindBy: An annotation used in Page Factory to locate and declare web elements using different locators. Below is an example of declaring an element using @FindBy
    @FindBy(id="elementId") WebElement element;

    Similarly, one can use @FindBy with different location strategies to find web elements and perform actions on them. Below are locators that can be used:

    • ClassName
    • CSS
    • Name
    • Xpath
    • TagName
    • LinkText
    • PartialLinkText
  • initElements()initElements is a static method in Page Factory class. Using the initElements method, one can initialize all the web elements located by @FindBy annotation.
  • lazy initialization: AjaxElementLocatorFactory is a lazy load concept in Page Factory. This is used to identify web elements only when they are used in any operation or activity. The timeout of a web element can be assigned to the object class with the help of the AjaxElementLocatorFactory.

 //create a Constructor
public classname(){

PageFactory.initElements(driver,this);
}

@FindBy(locator="locatorvalue")
private WebElement elementName;

@FindBy(locator="locatorvalue")
private WebElement elementName;


@FindBy(locator="locatorvalue")
private WebElement elementName;


Respective methods developed for above elements like doing actions on the elements, verifying whether that element is present in that page or not, page title is present or not. This is all developed using webdriver methods

public void clickElement(){
elementName.click();
}
=====================================================================
Why Page Object Model is better then Page Factory in Selenium?
PageFactory is an inbuilt POM concept in Selenium WebDriver, used for initialising Page objects or instantiating the Page object itself without using “FindElement" or "FindElements"

1) It uses annotations @FindBy to find WebElement, with attributes like tagName, partialLinkText, name, linkText, id, css, className, XPath.

2) "initElements()" is a method provided by the Page Factory class to initialize elements defined in a Page Object.

The initElements() method takes two parameters: a WebDriver instance and a Page Object instance. It scans the Page Object for any fields that are annotated with the @FindBy annotation and initializes them.

3) "@CacheLookUp" The end goal of this annotation is to make the code execute faster. It’s used mostly for WebElements in a test case. For the specific element, it keeps the WebElement in the cache memory after the first time it’s run.

Page Object Model:

Page Object Model (POM)
POM is a design pattern creating an Object Repository for web UI elements, aiming to reduce code duplication and improve test maintenance.

Each web page has a corresponding Page Class containing methods that perform operations on WebElements.

POM separates operations and flows in the UI from validation, making the code cleaner and more understandable.

It supports the reuse of page methods and gives methods realistic names for easy mapping with UI operations.

Why Not to use Page Factory?

(Refer this KeyNote from Selenium Team for its limitations: https://lnkd.in/gGsh3pgE)

1) The @CacheLookup annotation in PageFactory, intended for caching elements, can lead to StaleElementException If the DOM changes, it makes the element stale.
2) PageFactory is considered a “cumbersome and problematic implementation” with no significant benefits over direct runtime code element finding.













Did you implement interface in your automation?
Ans) yes
explanation: We have implemeneted ITestListener interface in our custom class. All the ITestListener interface methods are implemented in CustomListener class
ITestListener Interface Methods:
                        onFinish(ITestContext context)
Invoked after all the tests have run and all their Configuration methods have been called.
voidonStart(ITestContext context)
Invoked after the test class is instantiated and before any configuration method is called.
voidonTestFailedButWithinSuccessPercentage(ITestResult result)
Invoked each time a method fails but has been annotated with successPercentage and this failure still keeps it within the success percentage requested.
voidonTestFailure(ITestResult result)
Invoked each time a test fails.
voidonTestSkipped(ITestResult result)
Invoked each time a test is skipped.
voidonTestStart(ITestResult result)
Invoked each time before a test will be invoked.
voidonTestSuccess(ITestResult result)
Invoked each time a test succeeds.
-----------------------------------------------------------------------------------------------------------------------------
Where you have used java OOPS concepts in your automation Framework?
Ans) Java oops concepts are :
        1) Encapsulation
        2)Inheritance
        3)Polymorphysm
      4)Abstraction
Encapsulaiton:
Every Page class follows the encapsulation concepts. The page objects are declared as private and respective element methods are defined as public
Inheritance:
My TestBase class is extending to every testNG class.
ex
public clsss SearchTest extends TestBase{}
My TestBase class is extending to WebDriverUtility methods class.
EveryPage class will extend to WebDriverUtility class
Public class WebDriverUtility extends TestBase{}
public class HomePage extends WebDriverUtility{} -->MultiLevel Inheritance
Interface:
WebDriver is an interface. WebDriver abstract methods are implemented in RemoteWebDriver class. i.e we are overriding the WebDriver methods in the RemoteWebDriver class this is Following Method Overriding.
Wait is an Interface
JavascriptExecutor is an interface
Action is an interface
TakesScreenshot is an Interface
PolyMorphysm:
WebDriver driver=new ChromeDriver();
this is following RunTimePolymorphysm
MethodOverloading:
Actions class  is following method overloading concepts
click(), click(WebElement ele)
contextClick(), contextClick(WebElement ele);
ExpectedConditions class also following Methodoverloading concepts.
elementToBeClickable(By.locator("locatorvalue"));
elementToBeClickable(WebElement ele);
=========================================================================

hashtagExplain your framework to me. 🫠 👇

BDD Cucumber Framework explanation:
hashtagWe are using a maven Project to manage all dependencies which our project requires and using testNg framework. Along with testNg framework we are using Cucumber tool and implementing BDD Approach using Gherkin Keywords such as > hashtagGiven hashtagwhen hashtagAnd hashtagBut hashtagThen. Business Analyst are also involved in writing features file along with testing team.

hashtagFolder 1 (src/test/java) 📁
We have src/test/java folder where we have one package named hashtagrunner (It contains our Runner.java file from where we are running our tests. Here we are giving path of folder where all our features file are located and also using glue keyword which helps Cucumber locate the stepDefinition file. Along with that we are using tags like @smoke @sanity to run smoke or regression tests as per our requirement.

hashtagfeatures : We have one more package with name features where we maintained different features of our applications like Login.feature , Logout.feature etc.
👉 We are using Scenario keyword for above features file. If we want to run our test once. Also We are using Scenario Outline Keyword if we wanted to run our test multiple times with different sets of Data along with Examples Keyword (Very famous interview question. Use of Scenario vs Scenario Outline ) . We also added tags for each scenario like @smoke , @sanity etc.

hashtagstepDefinitions : We have one more package with name stepDefinitions that contains all the java files related to features (Login and Logout feature) like LoginTest.java and LogOutTest.java.

hashtaghooks : We have one more package with name as hooks. This package contains one java file with name MyHooks.java , this have two methods beforeScenario( ) and afterScenario( ). beforeScenario is used to run our chrome browser before each scenario and afterScenario is used to quit our browser after every scenario. We are using @Before annotation for beforeScenario method and @After annotation for afterScenario method.

hashtagFolder 2 (src/test/resources) 📁
Inside src/test/resources we have one package with name hashtagutilities where we maintained our data.properties file containing dev and test url. As we are using extent reports. We kept extent.properties file in this folder too 📁

hashtagFolder 3 (src/main/java) 📁
👉 In this folder we have one package named hashtagpageobjects where we stored all our locators for each webpage of our application.
-----------
hashtagtestng.xml: This file we have maintained to run multiple tests also this file is properly configured in our pom.xml file so we can easily run our testng.xml from maven command. Note : Memorize how testng.xml file looks sometimes interviewer can ask you to write sample testng.xml file on notepad.

hashtagOur Project is configured in jenkins we have provided our pom.xml path in jenkins and using mvn clean test command to run our test cases.
--------------------------------------------------------------------------------------------------
In this video, I have explained how to use JetBrains #Aqua IDE (Editor) for Selenium based projects. About Aqua: https://www.jetbrains.com/aqua/
download preview:https://www.jetbrains.com/aqua/download/#section=windows Designed for test automation: Aqua is the first JetBrains IDE created specifically for test automation. It's an all-in-one workspace that will help you boost your quality engineering productivity. Web Inspector: The embedded Web Inspector allows you to view web applications in Aqua and capture any page elements required for automated tests. Working like a built-in browser, the Web Inspector lets you stay inside the IDE without switching to another tool. Support for popular testing frameworks: Aqua supports the Selenium, Cypress, and Playwright testing frameworks, enabling you to create and run automated UI tests using your preferred tools. With JetBrains Aqua, you can write, run, and debug unit tests using JUnit, pytest, Jest, and other tools. Support for multiple languages: Aqua is an IDE that understands Java, Python, JavaScript, TypeScript, Kotlin, and SQL. Just like any other JetBrains IDE, Aqua has powerful code completion and refactoring capabilities, helpful on-the-fly inspections, and a user-friendly debugger and test runner. Modern UI: A modern and intuitive user interface makes it easy for both beginners and experienced professionals to get started with Aqua. Comprehensive feature set: Aqua boasts a rich feature set with our HTTP Client for API testing, support for popular databases, and integration for Docker and version control. This feature set is available out of the box.


JetBrains Aqua – An IDE for Writing Tests You Can Be Proud Of.

In Aqua, we’ve assembled everything a test automation engineer needs on a daily basis, including a multi-language IDE (with support for JVM, Python, and JavaScript, and others), an HTTP client, database management functionality, Docker support, a TMS client, and a new, powerful web inspector for UI autom


Why do you need Aqua?

Designed for test automation

Aqua is the first JetBrains IDE created specifically for test automation. It's an all-in-one workspace that will help you boost your quality engineering productivity.

Web Inspector

The embedded Web Inspector allows you to view web applications in Aqua and capture any page elements required for automated tests. Working like a built-in browser, the Web Inspector lets you stay inside the IDE without switching to another tool.

Aqua’s embedded Web Inspector generates a unique CSS or XPath locator for a selected element on a web page and adds it to the source code. When Web Inspector is active, CSS and XPath code completion suggests and highlights locators for the most important web page elements.



Support for popular testing frameworks

Aqua supports the Selenium, Cypress, and Playwright testing frameworks, enabling you to create and run automated UI tests using your preferred tools. With JetBrains Aqua, you can write, run, and debug unit tests using JUnit, pytest, Jest, and other tools.

Comprehensive feature set

Aqua boasts a rich feature set with our HTTP Client for API testing, support for popular databases, and integration for Docker and version control. This feature set is available out of the box.

Support for multiple languages

Aqua is an IDE that understands Java, Python, JavaScript, TypeScript, Kotlin, and SQL. Just like any other JetBrains IDE, Aqua has powerful code completion and refactoring capabilities, helpful on-the-fly inspections, and a user-friendly debugger and test runner.

Modern UI

A modern and intuitive user interface makes it easy for both beginners and experienced professionals to get started with Aqua

==============================================================
Creating Maven Project with above components:

Open Eclipse and Click on File – New – Project.
Select Maven – Maven Project as below :


Click next. Following window will appear :
Click on Create a simple project(skip archetype selection)

Click Next. Following window will appear :


Fill the required information as above.
Click Finish. Your project will be created as below :

Make sure pom.xml is created. We need to add maven dependenices in pom.xml file.
pom.xml contains four sections:
1)Project information
2)properties section
3)build section
4)dependencies section

Complete pom.xml file with all dependencies, build and properties sections
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>HybridAutomationFrameowrkNov302022</groupId>
  <artifactId>HybridAutomationFrameowrkNov302022</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
 <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>
  
  <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
     <source>1.8</source>
     <target>1.8</target>
    </configuration>
   </plugin>

   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19.1</version>
    <configuration>
     <suiteXmlFiles>
      <suiteXmlFile>src/test/resources/TestNG/TestNG.xml</suiteXmlFile>
     </suiteXmlFiles>
    </configuration>
   </plugin>
  </plugins>
<resources>
  <resource>
  <directory>src/test/java/com/qa/linkedin/config</directory>
  </resource>
  </resources>
 </build> 
  
    <dependencies>
  <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.6.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.testng/testng -->
<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>7.6.1</version>
    <scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.19.0</version>
</dependency>


    <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.19.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml-schemas</artifactId>
    <version>4.1.2</version>
</dependency>

 <!-- https://mvnrepository.com/artifact/com.aventstack/extentreports -->
<dependency>
    <groupId>com.aventstack</groupId>
    <artifactId>extentreports</artifactId>
    <version>4.0.9</version>
</dependency>


  
  </dependencies>
 
</project>
===============================================

Different Ways to run Framework Tests:


1)Run tests through testNG.xml


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="linkedinSuite">
<listeners>
     <listener class-name="com.qa.linkedin.listeners.ExtentReportListener"></listener>
  </listeners>
  <test thread-count="5" name="linkedinTest">
    <classes>
      <!-- class name="com.qa.linkedin.testcase.LinkedinHomeTest"/ -->
      <class name="com.qa.linkedin.testcase.SearchPeopleTest"/>
    </classes>
  </test> <!-- linkedinTest -->
</suite> <!-- linkedinSuite -->

Include all the test case classes in testNg.xml file then-->run as testNg Suite
While running through testNG.xml if you see below error

java.lang.NoClassDefFoundError: freemarker/template/TemplateModelException #295

Solution: add the fremarker dependency in pom.xml
<!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.31</version>
</dependency>

problem2)
if you see below error 

java.lang.Error: Unresolved compilation problem: VERSION_2_3_29 cannot be resolved or is not a field #110


Solution:change the extentreports version from 4.1.0 to 4.1.1

Problem related to log4j:
[Utils] [ERROR] [Error] java.lang.NoSuchMethodError: org.apache.logging.log4j.Logger.atDebug()Lorg/apache/logging/log4j/LogBuilder;

Solution is:

The isTraceEnabled() method has been added to log4j 1.2.12, according to the Javadoc:
https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Logger.html#isTraceEnabled()

If you're using log4j (also if this is a transitive dependency on your project setup), please ensure that you take the latest version of log4j

Related link:https://github.com/jOOQ/jOOQ/issues/2085

2)Run tests through pom.xml


Add build configurations inside the pom.xml then mention the testNG.xml file

<build>
<plugins>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>

<suiteXmlFiles>
<suiteXmlFile>src/test/resources/TestNgSuite/testNG.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>

</plugins>

</build>



right click on pom.xml-->run as -->maven clean
right click on pom.xml-->run as -->maven install or maven test
right click on pom.xml-->run as -->maven build-->goals-->clean install-->apply-->run

3)Run tests through command prompt

1)Download maven to your local machine from below url
click on Binary zip archive apache-maven-3.8.5-bin.zip
place the zip file in c drive- one folder named: apachemaven

Unzip the compresed maven file
go to maven folder
go to environment variables 
click on New button
set the variable name as:MAVEN_HOME and value as:C:\ApacheMaven\apache-maven-3.8.5-bin\apache-maven-3.8.5 under system variables 
select the path variable--click on edit
click on new button in open window
%MAVEN_HOME%\bin
click ok-->ok-->ok
Go to project location
open project location in command prompt -->then type below command
mvn clean install

4)Run tests through batch file

create a batch file(run.bat) under project locaiton and include below two lines
cd D:\eclipseworkspaceAug2018\HybridFrameworkWeekendApril52020
mvn clean install
save file as run.bat file-->then double click on the bat file--tests will be triggered.
Note:No need to go to eclipse to triggere the tests with this process.

5)Run tests through Jenkins CI tool

What is Continuous Integration?
Continuous Integration is a development practice in which the Automation Testers are required to commit changes to the source code in a shared repository several times a day or more frequently. Every commit made in the repository is then built. This allows the teams to detect the problems early. Continuous Integration is the most important part of DevOps that is used to integrate various DevOps stages. Jenkins is the most famous Continuous Integration tool.
What is Jenkins?
Jenkins is an open source automation tool written in Java with plugins built for Continuous Integration purpose. Jenkins is used to build and test your software projects continuously making it easier for developers to integrate changes to the project, and making it easier for users to obtain a fresh build. It also allows you to continuously deliver your software by integrating with a large number of testing and deployment technologies. Jenkins integrates development life-cycle processes of all kinds, including build, document, test, package, stage, deploy, static analysis and much more. Jenkins achieves Continuous Integration with the help of plugins. Plugins allows the integration of Various DevOps stages. If you want to integrate a particular tool, you need to install the plugins for that tool. For example: Git, Maven, HTML publisher etc.

Advantages:
  • Advantages of Jenkins include:
  • It is an open source tool with great community support.
  • It is easy to install.
  • It has 1000+ plugins to ease your work. If a plugin does not exist, you can code it and share with the community.
  • It is built with Java and hence, it is portable to all the major platforms.
Apart from Jenkins, we have many more tools in the market such as:
  • Anthill
  • Bamboo
  • Cruise Control
  • Team City
Complete Jenkins Installation Process
URL: https://www.jenkins.io/download/ 

Download the jenkins.war file from below location:
latest stable Jenkins WAR file


Place jenkins.war file in c drive


Open jenkins.war file location in command prompt 


Go to jenkins downloaded folder location, Default port is 8080, no need to specify port if your jenkins running on 8080 port
provide below command in command prompt: to start the jenkins server
 java -jar jenkins.war

Then Press ENTER key from keyboard

if you want to start the jenkins in particular port use below command
java -jar jenkins.war --httpPort=8082


copy the password from command prompt console or 
goto the location for password:C:\Users\LENOVO\.jenkins\secrets\initialAdminPassword
STEP1:
open any browser & type below url in address bar
localhost:8080 or localhost:portnumber -->press enter key
Step2)
Enter the Administrator password that is copied from commandprompt or terminal

Step3):
After entering the password click on continue button
select  install suggested plugins option

Step4):
it will install all the suggested plugins


Step5): 
create username and password in below screen







STEP6)after setting username and password then login to jenkins
we will see welcome to jenkins page like below


complete the installation


Manage Jenkins(configuring the jenkins)-->Manage Plugins
install Html Publisher plugin(Note :https://plugins.jenkins.io/htmlpublisher/)
The HTML Publisher plugin is useful to publish HTML reports that your build generates to the job and build pages. It is designed to work with both Freestyle projects as well as being used in a Jenkins Pipeline.
maven integration plugin
Green Balls
create a job
trigger build
NOTE: if Jenkins installation is already done and the session is closed, just start the Jenkins server from the command prompt using the below command
java -jar jenkins.war
and wait for the message
jenkins is fully up and running in commond prompt console
then go to any browser & type below url in addressbar
localhost:8080
then page will open with jenkins login page then perform the login with username and password created during the installation
Configure Email Notification in Jenkins|How To Send Email from Jenkins Job:
Note:https://plugins.jenkins.io/email-ext/
1)click on manage Jenkins from the left panel

2)Click on Configure System
3)Enter Details SMTP server and Port in the Extended Email Notification section like the below screen
click on Advanced button

Under the Credentials, section click on add-->select Jenkins
Now Jenkins Credentials provider popup will be displayed
select the Kind option username with password

Enter username -
rameshitusa29@gmail.com and password[gmal app password need to be provided here]
Description:unique name for credentials
click on Add button 
default content type: plain/text
default Recipients:rameshitusa29@gmail.com
Enter default subject:
Automation Report - $PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS
Enter default content:
Hi,
Please find the Automation job summary report
 $PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS
Check console output at $BUILD_URL to view the results.
Thanks,
Automation Team
Note: Please do not reply to this email




Enter the details in the Email Notification Section
provide SMTP server:smtp.gmail.com
default user email suffix:@gmail.com
click on advanced
check the use SMTP Authentication checkbox
Enter username rameshitusa29@gmail.com and password[gmal app password need to be provided here]
check the use SSL checkbox

enter Gmail SMTP port:465
Click on Test Configuration by sending the test email checkbox
Enter the recipient's email address
Click on Test Connection

One Test Email should be sent

Click on Save and Apply buttons.
----------------------------------------------
Note:
navigate to https://myaccount.google.com/
click on Security on left panel

turn on 2 step verification
click on app password

It might ask you the password again enter it 
then below page will be shown
Select app :mail
select device:windows computer


Click on Generate button
Copy the 16 character App password:
flmzzrxjphqdjkfo


Click on Done
NOTE: Use the above password in Jenkins

The setting that you are looking for is not available for your account.” – this means 2-Step Verification is not enabled on your account. Enable it first.

=======================================================================
Create a job and test the email 
under build section select editable email notification option

Enter project recipients list
rameshitusa29@gmail.com,rameshn3@gmail.com

click on advanced
trigger part:when do you want to trigger the build
click on save and apply
====================================
Integrate Selenium Maven Github project in Jenkins:
1)first push the code to the GitHub
2)go to Jenkins
3)click on New Item name:integrategithubwith jenkins to create a new job
4)select maven project

5)Click on the Ok button
6)Enter the description: integrating selenium GitHub project in Jenkins
7)Source Code Management section-->select git radio button
8)Copy the Github code url like below

9)Enter Repository URL in jenkins job:
https://github.com/rameshn3/HybridFrameworkOct262022.git


10)click on add under Credentials -->select Jenkins

11)Select Kind:username with Password
Enter username:rameshn3@gmail.com
Password:********
Description:GithubCredentials
click on Add button
select the branch you want to run either */master or specific branch:automationtaskNov32022
Refer more:https://stackoverflow.com/questions/23906352/git-pullrequest-job-failed-couldnt-find-any-revision-to-build-verify-the-repo

12)give Root pom from github like below
Note: if you parameterise the pom.xml like step14
Goals and options should be like below


13)Under post steps select run regardless of build result
14)In Your Project pom.xml parameterise the build section plugin-surefire plugin like below, then commit to github

Click on Apply and Save buttons
Then trigger the build
It will download the project from GitHub and runs the testcases
====================================

Groovy's Domain-Specific Language (DSL) for Jenkins Pipelines


Introduction

In today's fast-paced development environment, automation is key to delivering software quickly and reliably. Jenkins, a leading open-source automation server, enables continuous integration and continuous delivery (CI/CD) for any project. At the heart of Jenkins is the Pipeline, which uses Groovy-based Domain-Specific Language (DSL) to automate build, test, and deployment processes. This article explores Groovy's DSL for Jenkins Pipelines, explaining its terminologies, structure, and usage through detailed examples.

Key Terminologies

Before diving into the DSL, it's crucial to understand the key terminologies:

1. Pipeline: A Pipeline defines a series of automated steps that take your code from version control to production.

2. Groovy: Groovy is an object-oriented programming language that enhances Java and is used to script Jenkins Pipelines.

3. DSL (Domain-Specific Language): A specialized language designed to solve problems in a specific domain—in this case, defining Jenkins Pipelines.

4. Stage: A stage is a block that groups steps in a Pipeline, typically representing a phase like "Build," "Test," or "Deploy."

5. Step: A step is a single task that Jenkins performs, such as running a shell command or executing a script.

6. Agent: An agent specifies where the Pipeline or a particular stage runs, whether on any available node, a specific node, or within a Docker container.

Step-by-Step Guide to Groovy DSL for Jenkins Pipelines

Step 1: Creating a Jenkins File

The Jenkinsfile is a text file containing the Pipeline definition, written using Groovy DSL. It should be placed in the root directory of your repository.


pipeline {

    agent any

    stages {

        stage('Build') {

            steps {

                echo 'Building...'

            }

        }

        stage('Test') {

            steps {

                echo 'Testing...'

            }

        }

        stage('Deploy') {

            steps {

                echo 'Deploying...'

            }

        }

    }

}


Step 2: Defining Agents

Agents specify where the Pipeline or a specific stage runs. The agent any directive indicates that the Pipeline can run on any available agent.


pipeline {

    agent {

        label 'my-agent-label'

    }

    stages {

        // Stages go here

    }

} 

Step 3: Creating Stages and Steps

Stages are used to organize the Pipeline into discrete phases. Each stage can contain multiple steps that perform specific tasks.


stage('Build') {

    steps {

        sh 'make' // Execute shell command to build the project

    }

}

stage('Test') {

    steps {

        sh 'make test' // Execute shell command to test the project

    }

}

stage('Deploy') {

    steps {

        sh 'make deploy' // Execute shell command to deploy the project

    }

} 

Step 4: Using Post-Actions

Post actions are blocks that define steps to run at the end of a Pipeline or stage, regardless of the outcome.

post {

    always {

        echo 'This will always run'

    }

    success {

        echo 'This will run only if the Pipeline succeeds'

    }

    failure {

        echo 'This will run only if the Pipeline fails'

    }

}


Step 5: Parallel Execution

Jenkins Pipelines can run multiple stages in parallel to optimize the CI/CD process. This is done using the parallel directive.

stage('Parallel Execution') {

    parallel {

        stage('Unit Tests') {

            steps {

                sh 'make test-unit'

            }

        }

        stage('Integration Tests') {

            steps {

                sh 'make test-integration'

            }

        }

    }

} 

Practical Examples

Example 1: Simple Pipeline

This example demonstrates a basic Pipeline with build, test, and deploy stages.

pipeline {

    agent any

    stages {

        stage('Compile') {

            steps {

                echo 'Compiling..'

                sh 'javac MyClass.java'

            }

        }

        stage('Unit Test') {

            steps {

                echo 'Running Unit Tests..'

                sh 'java MyClassTest'

            }

        }

        stage('Deploy') {

            steps {

                echo 'Deploying Application..'

                sh 'scp MyClass.class user@host:/deploy'

            }

        }

    }

} 

Example 2: Declarative Pipeline with Notifications

This example shows how to add email notifications for success and failure outcomes.


pipeline {

    agent any

    stages {

        stage('Build') {

            steps {

                echo 'Building...'

                sh 'make build'

            }

        }

        stage('Test') {

            steps {

                echo 'Testing...'

                sh 'make test'

            }

        }

    }

    post {

        success {

            mail to: 'team@example.com',

                 subject: "Build Successful: ${env.JOB_NAME} ${env.BUILD_NUMBER}",

                 body: "Good job! The build was successful."

        }

        failure {

            mail to: 'team@example.com',

                 subject: "Build Failed: ${env.JOB_NAME} ${env.BUILD_NUMBER}",

                 body: "Unfortunately, the build failed. Please check the Jenkins logs for more details."

        }

    }

}

FAQs

Q1: What is the primary benefit of using Groovy DSL for Jenkins pipelines?

A1: The primary benefit is the ability to define complex, multi-step workflows in a clear, readable, and maintainable manner. Groovy DSL's flexibility allows for the customization of build, test, and deployment processes to fit specific project requirements.

Q2: Can I use Jenkins Pipelines without knowing Groovy?

A2: While a basic understanding of Groovy helps in writing and maintaining Jenkins Pipelines, the DSL is designed to be user-friendly. Jenkins' documentation and community support can assist in learning the necessary Groovy basics.

Q3: How do I debug issues in my Jenkins Pipeline?

A3: You can use the echo command to print debug information to the Jenkins console. Additionally, Jenkins provides detailed logs for each step of the Pipeline, which can help identify and resolve issues.

Q4: What is the difference between Declarative and Scripted Pipelines in Jenkins?

A4: Declarative Pipelines provide a more structured and user-friendly syntax, ideal for simpler, standardized tasks. Scripted Pipelines offer greater flexibility and are suited for more complex, customized workflows. Both use Groovy DSL but differ in their structure and capabilities.

Q5: How do I handle parallel execution in Jenkins Pipelines?

A5: You can define parallel stages in a Jenkins Pipeline using the parallel directive. This allows multiple stages to run simultaneously, speeding up the overall pipeline execution.


stage('Parallel Execution') {

    parallel {

        stage('Unit Tests') {

            steps {

                sh 'make test-unit'

            }

        }

        stage('Integration Tests') {

            steps {

                sh 'make test-integration'

            }

        }

    }

} 

Conclusion

Groovy's DSL for Jenkins Pipelines offers a powerful and flexible way to define CI/CD workflows. By understanding the core concepts and leveraging the provided examples, you can create robust Pipelines tailored to your project's needs. Whether you're a novice or an experienced DevOps engineer, mastering Jenkins Pipelines will significantly enhance your automation capabilities.