Configure Log4j | Data Driven Framework | Part 4

Data Driven Framework Tutorial

 

Logs provide an easy way to debug the execution flow. We will use log4j Logger to capture 2 types of logs:

  • appliction.log – contains user-defined logs 
  • selenium.log – this log contains extra information generated by selenium

To implement the log in our data driven framework, we must fulfill the following criteria:

  • log4j.properties file – to initialize the log4j appender. We will use devpinoyLogger as an appender
  • Logger class reference variable to initialize the devpinoyLogger appender

We will call the Logger class reference variable in the TestBase class and use the debug method to attach the log in our framework.

 

 

Create log4j.properties class

 

The log4j.properties file primarily contains the following information:

  • target where the logs should be displayed/stored. We will store the logs in 2 different files (as mentioned above)
  • appender information (devpinoyLogger)
  • file destinations

Create a new file log4j.properties inside package src/main/resources

 


#Root logger option
log4j.rootLogger=debug,file
log4j.appender.file=org.apache.log4j.RollingFileAppender
#path where selenium log should be stored
log4j.appender.file.File=E:\\eclipse-workspace\\DataDrivenPattern\\src\\test\\resources\\logs\\selenium.log
log4j.appender.file.maxFileSize=5000KB
log4j.appender.file.maxBackupIndex=1
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
#do not append the old file. Create a new log file everytime
log4j.appender.file.Append=false

#Application Logs
log4j.logger.devpinoyLogger=DEBUG, dest1
log4j.appender.dest1=org.apache.log4j.RollingFileAppender
log4j.appender.dest1.maxFileSize=5000KB
log4j.appender.dest1.maxBackupIndex=3
log4j.appender.dest1.layout=org.apache.log4j.PatternLayout
log4j.appender.dest1.layout.ConversionPattern=%d{dd/MM/yyyy HH:mm:ss} %c %m%n
#path where application log should be stored
log4j.appender.dest1.File=E:\\eclipse-workspace\\DataDrivenPattern\\src\\test\\resources\\logs\\application.log
#do not append the old file. Create a new log file everytime
log4j.appender.dest1.Append=false

 

The existing data will not be retained every time you execute the suite. If you wish to persist the older data as well, change file.Append and dest1.Append to true.

If you do not place the log4j.properties file inside the suggested package, then logs may not generate.

 

Logger Class Object Variable

 

Create a Logger class object variable in TestBase class and invoke the devpinoyLogger. 

 

//Create Logger class object to initialize the log4j
    public static Logger logger = Logger.getLogger("devpinoyLogger");

 

Now we can use the logger.debug() method to generate our customized logs. Just use logger.debug(“your message”) and it will be written to application.log file during execution. Update the TestBase.java class as following (highlighted in bold):

 

package com.appliedselenium.base;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;

public class TestBase {

    //initialize the WebDriver interface reference variable
    public static WebDriver driver;

    // Create instance of Properties class to refer the .properties file
    public static Properties or = new Properties();
    public static Properties config = new Properties();

    // Create filestream class object to load the file
    public static FileInputStream fis;
    
    //Create Logger class object to initialize the log4j
    public static Logger logger = Logger.getLogger("devpinoyLogger");
    
    //Generic Method to check the presence of an element
    //This method accepts 1 parameter by of type By and returns a boolean value
        public boolean isElementPresent(By by) {
            
            try {
                driver.findElement(by);
                return true;
            }catch (NoSuchElementException e) {
                return false;
            }
            
        }

    // First method to be called before automation suite is executed 
    @BeforeSuite
    public void setUp() {
        
        //check if driver reference variable is null, i.e. no browser is opened through selenium yet
        if (driver == null) {

            //get the reference of or.properties file
            try {
            
                fis = new FileInputStream(
                        System.getProperty("user.dir") + "\\src\\test\\resources\\properties\\or.properties");
            } catch (FileNotFoundException e) {
                
                e.printStackTrace();
            }
            
            //load the file into memory
            try {
                or.load(fis);
                logger.debug("or.properties file loaded");

            } catch (IOException e) {
                
                e.printStackTrace();
            }

            //get the reference of config.properties file
            try {
                fis = new FileInputStream(
                        System.getProperty("user.dir") + "\\src\\test\\resources\\properties\\config.properties");
            } catch (FileNotFoundException e) {
                
                e.printStackTrace();
            }
            
            //load the file into memory
            try {
                config.load(fis);
                logger.debug("config.properties file loaded");
            } catch (IOException e) {
                
                e.printStackTrace();
            }

            // invoke the browser mentioned in config.prop and assign it to driver reference variable
            if (config.getProperty("browser").equals("chrome")) {
                System.setProperty("webdriver.chrome.driver",
                        System.getProperty("user.dir") + "\\src\\test\\resources\\executables\\chromedriver.exe");
                driver = new ChromeDriver();
                logger.debug("Chrome browser launched");
            }

            //open the url and assign an implicit wait (as configured in config.properties)
            driver.get(config.getProperty("url"));
            logger.debug("Application launched: "+config.getProperty("url"));
            driver.manage().window().maximize();
            driver.manage().timeouts().implicitlyWait(Integer.parseInt(config.getProperty("implicit_wait")),
                    TimeUnit.SECONDS);
        }

    }

    // Mehod called after all the tests are executed
    @AfterSuite
    public void tearDown() {
        System.out.println("Closing the browser");
        driver.quit();
        logger.debug("Browser Closed");

    }

}

 

Similarly, we can use logger reference in our test class. Update the CheckLoginTest class as follows:

 

package com.appliedselenium.testscripts;

import org.openqa.selenium.By;
import org.testng.Assert;
import org.testng.annotations.Test;

import com.appliedselenium.base.TestBase;

//Test class name should end with Test
//All the test classes must extend TestBase
public class CheckLoginTest extends TestBase {

    // @Test annotation is used to create a test method
    @Test
    public void testLogin() {

        logger.debug("Inside testLogin()");

        // enter the username and password. These values are stored in config.properties
        // file and locators are stored in
        // or.properties file
        driver.findElement(By.xpath(or.getProperty("username_XPATH"))).sendKeys(config.getProperty("user_name"));
        logger.debug("user name entered: " + config.getProperty("user_name"));

        driver.findElement(By.xpath(or.getProperty("passwd_XPATH"))).sendKeys(config.getProperty("password"));
        logger.debug("Password entered: " + config.getProperty("password"));

        driver.findElement(By.xpath(or.getProperty("loginBtn_XPATH"))).click();
        logger.debug("Log in button clicked");

        // create a method isElementPresent() in TestBase to verify the presence of an
        // element
        // if element is found then pass the test else fail the test with message "Login
        // not successful"
        Assert.assertTrue(isElementPresent(By.xpath(or.getProperty("logout_XPATH"))), "Login not successful");

        // this log will only be printed if above assertion is passed
        logger.debug("Login Successful");

    }

}

 

Execute the suite using TestNG. Upon test execution completion, refresh the project. You should see 2 log files generated inside src/test/logs folder, containing all the logs which we have written inside logger.debug().

In next tutorial of data driven framework, we will create another test class and use dataProvider to fetch the data from excel sheet. If not already, please download the ReadExcel.java utility class from https://github.com/DhawalGit/ReadExcelUtility.git and place it inside com.appliedselenium.utilities package. Explore the methods in this class and get familiar with how to manipulate excel data.

You may save this class to your google drive or any other cloud location for easy access. It will help you in your projects as well or wherever you need to manipulate excel data.

 

Author: Dhawal Joshi

A post-graduate in MCA, ISTQB & ITIL certified QA with more than 8 years of experience in QA working with a CMMI Level 5 organization as System Analyst. I started my automation journey with HP UFT(formerly known as QTP) and for the past few years, I am using Selenium for automation. I also have experience in Android Application Development, Java, HTML, and VBScript. When I am not working, I like to spend time with my family, cooking and learning new developments in IT.

Leave a Reply

Your email address will not be published. Required fields are marked *