Debugging Selenium Scripts with Logs (Log4j Tutorial) – Selenium Tutorial #26

Now we are moving towards the end of our most comprehensive Free Tutorials for Selenium Testing tool. The tutorials we are posting now are the part of advance Selenium training.

In the previous tutorial, we kept our focus on the Continuous Integration tool named as Hudson. It’s a free tool and has a lot more capabilities to build the testing project, execute the test classes remotely and send out a notification email across the stakeholders informing them about the application status with respect to passed and failed test cases.

In the current tutorial, we would motion towards some advance concepts that would directly or indirectly help in optimizing the Automation framework and brings more visibility to the users.

Thus, in the current tutorial, we would discuss about the logging feature, its potential, debugging capabilities and much more.

Sometimes logging is considered to be an overhead upon the existing script creation mechanism but experts considers it to be one of the best practices if used in the accurate proportion because of the following advantages:

Advantages of Logging in Selenium Scripts:

  • Grants a complete understanding of test suites execution
  • Log messages can be stored in external files for post execution scrutiny
  • Logs are an exceptional assistant in debugging the program execution issues and failures
  • Logs can also be reviewed to ascertain the application’s health by the stakeholders

Log4j – A Java based Logging API

Moving on to the technical details about logging, let us discuss the origin of the API that we would be using throughout the log4j tutorial to generate logs. Log4j was a result of collaborative efforts of people at Secure Electronic Marketplace for Europe to develop a utility that would help us generating logs and hence the log4j came into limelight in the year 1996. Log4j is an open source tool and licensed under IBM Public License.

There are three main components that constitute the implementation of log4j. These components represent the details about the log level, formats of the log message in which they would be rendered and their saving mechanisms.

Constituents of Log4j

  1. Loggers
  2. Appenders
  3. Layouts

#1) Loggers

The following steps need to done in order to implement loggers in the project.

Step 1: Creating an instance of Logger class

Step 2: Defining the log level

Logger Class – It is a java based utility that has got all the generic methods already implemented so that we are enabled to use log4j.

Log levels – Log levels are popularly known as printing methods. These are used for printing the log messages. There are primarily five kinds of log levels.

  • error()
  • warn()
  • info()
  • debug()
  • log()

Thus, to be able to generate logs, all we need to do is to call any of the printing method over the logger instance. We will have a broader look into it during the implementation phase.

#2) Appenders

Now that we know how to generate these logs, the next thing that should pop up into our minds is that where do I get to view the logs? The answer to this question lies in the definition of “Appenders”.

Appenders are consistently used to specify the data source/medium where the logs should be generated. The scope of data sources stretches from various external mediums like console, GUI, text files etc.

#3) Layouts

At times, user wishes certain information to be pre – pended or appended with each log statement. For example I wish to a print a timestamp along with my log statement. Thus, such requirements can be accomplished by “Layouts”.

Layouts are a utility that allows the user to opt for a desired format in which the logs would be rendered. Appenders and Layout have a tight coupling between them. Thus, we are required to map each of the appender with a specific layout.

Take a note that user is leveraged to define multiple appenders, each mapped with a distinct layout.

Now that we are aware of the basics of log4j and its components, we shall motion our focus towards the implementation phenomenon.

Let us understand the entire implementation process step by step.

Installation/Setup

For the installation and setup, we would be considering “Learning_Selenium” project that we have already created in the earlier sessions of this series.

Step 1: The first and the foremost step is to download the latest jar for log4j API. The jar can be easily found at its official distribution website – “http://logging.apache.org/log4j/1.2/download.html”.

Step 2: The next step is to configure the build path and provide log4j.jar as an external library.

Implementation

Logging using log4j can be implemented and configured in namely two ways:

  1. Programmatically via script
  2. Manually via Configuration files

Both the above mentioned configuration methods have merit as well as demerits. For this tutorial, we would consider configuring log4j manually via Configuration files based on its ease and simplicity. Configuration file is yet another xml file to configure artifacts related to log4j.

Creation of log4j.xml file

Step 1. Create a log4j.xml file. Copy and paste the code below in the configuration file.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<!-- For Printing message with date , time & class name also
<param name="ConversionPattern" value="%d{dd MMM yyyy HH:mm:ss} %5p %c{1} - %m%n"/>
-->
<!-- For printing message only -->
<param name="ConversionPattern" value="%-5p[%c{1}]: %m%n"/>
</layout>
</appender>
<appender name="fileAppender" class="org.apache.log4j.RollingFileAppender">
<param name="append" value="false"/>
<param name="file" value="Logs/Webliv_Automation_Logs.log"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{dd-MM-yyyy HH:mm:ss}%x %-5p[%c{1}]: %m%n"/>
</layout>
</appender>
<root>
<level value="INFO"/>
<appender-ref ref="consoleAppender"/>
<appender-ref ref="fileAppender"/>
</root>
</log4j:configuration>

Walkthrough of Configuration File

consoleAppender

<appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">

The consoleAppender is used to print the log statements on the console.


fileAppender

<appender name="fileAppender" class="org.apache.log4j.RollingFileAppender">

The fileAppender is used to print the log statements within an external file. User is leveraged to set an on and off value for the append tag which would tell the system to append and log statements to the previously created one or to overwrite the previously created logs and generate the fresh logs altogether.

<param name=<em>"append"</em> value=<em>"false"</em>/>
<param name="file" value="Logs/TestLogs.log"/>

The value of the file parameter is set to a particular location to notify the system to create the anticipated log file at the said location. We also specify the log file name within the value parameter.

Layout

<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{dd-MM-yyyy HH:mm:ss}%x %-5p[%c{1}]: %m%n"/>
</layout>

As discussed in the early sections of this tutorial, the layouts are used to specify the rendering mechanism for log statements. Log4j provides various layout patterns. User is leveraged to specify the desired pattern in the value of ConversionPattern parameter.

The output of the above layout should be something like:

01-07-2014 12:56:32 INFO [GmailLogin]: Sample log message

In the output above:

  • First field – Date of execution
  • Second field – Exact time in hh:mm:ss at which the test step was executed
  • Third field – One of the log level
  • Fourth field – Name of the test class
  • Fifth field – Log message

Step 2. As soon as we are done with the creation of log4j.xml file, the next step is to put the log4j.xml file into the project’s root folder/base directory.

Program level Implementation

Step 3: The next step is to use any of the configurator to configure and parse the log4j.xml file.

Syntax:

package com.logExample;
import org.apache.log4j.xml.DOMConfigurator;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.RunWith;
import org.junit.runner.notification.Failure;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
                Demo.class
                                })
public class TestSuite {
                /**
                 * Setup method to set system property for log file name
                 */
                @BeforeClass
                public static void Setup() {
                                // loading log4j.xml file
                               DOMConfigurator.configure("log4j.xml");
                }
                /**
                 * @param args
                 */
                public static void main(String[] args) {
                                Result result = JUnitCore.runClasses(TestSuite.class);
                                for (Failure failure : result.getFailures()) {
                                                System.out.println("\nTEST NAME: " + failure.getTestHeader());
                                                System.out.println("\nERROR: " + failure.getMessage() + "\n");
                                                System.out.println(failure.getTrace());
                                                System.exit(1);
                                }
                }             
}

Note: Logs can be implemented at the class level also instead of Test suite level. All you need to do is to make the required changes in the test class rather than in the test suite.

Step 4: The very next step is to create a test class “GmailLogin.java” under the project. Implement the Gmail login functionality with in the class.

Step 5: The next step is to import the logger class to be able to implement the log statements.

Syntax:

import org.apache.log4j.Logger;

Step 6: The next step in the process is to instantiate the object of the Logger class.

Syntax:

//Object initialization for log

       static Logger log = Logger.getLogger(Demo.class.getName());

Step 7: The above created log variable of type Logger would be used across the entire test class to generate the log statements. Refer the following code for the same.

Syntax:

@Test
public void testGmailLogin() throws Exception{
// enter a valid email address
driver.findElement(By.id("Email")).sendKeys("TestSelenium1607@gmail.com");
log.info("Entered a valid Email Address.");
// enter a invalid password
driver.findElement(By.id("Passwd")).sendKeys("InvalidPassword");
log.info("Entered a invalid Password.");
// click on sign in button
driver.findElement(By.id("signIn")).click();
log.info("Clicked on the Sign In Button.");
try{
//Verify the home page
assertTrue("Verification Failed: User successfully landed on the Home Page.", driver.getTitle().equals("Gmail"));
log.info("Verified that the user landed on the Home Page.");
}
catch (Exception e)
{
log.error("Unsuccessfull Login.");
}
}

Result in the log file

01-07-2014 12:56:11 INFO [GmailLogin]: Uploaded the file to the System: FileExample.txt
01-07-2014 12:56:11 INFO [GmailLogin]: Submitting the changes
01-07-2014 12:56:15 ERROR [GmailLogin]: Unsuccessful Login.

Conclusion

In the current tutorial, we pressed our focus on the technical implication while implementing logging in a framework. We exploited log4j utility to implement logging. We discussed the basic components those constitute log4j from a usability perspective. With the Appenders and layouts, user is leveraged to choose the desired logging format/pattern and the data source/location.

Next Tutorial #27: In the upcoming tutorial, we would discuss some more advanced topics related to efficient scripting and to troubleshoot scenarios where the user is required to handle mouse and keyboard events. Moreover, we would also discuss how to store more than one web element in a list.




Recommended reading

5 comments ↓

#1 Saranraj

Hi,

I’m newbie to log4j.I’m trying to implement log4j in my framework. I would like to configure it in manually via configuration files. Could you please explain the configuring log4j manually via configuration files in more detailed manner?

Regards,
Saranraj

#2 Victor

Hello,
Can you please also add in this tutorial how to configure log4j to work with TestNG? Thank you.

#3 MINNU JAYAPRAKASH

log 4j is not wrkng ..plz help

#4 Sathya

Author did not intended to provide enough info. Plus, at the same time wanted to get credit for “so called helping article” which don’t work

#5 harish

I am working on a dummy project where i am using Log4j reporting. I implemented log4j and used in all methods and test cases and it is working fine. But when i run the test cases by using TestNG Groups with the testng.xml it’s throwing error message. It’s asking me to implement listeners class.

I created a dummy listener class and pasted but log 4j is not working i am not getting the log file if i run the tests through testng.xml.

My code works absolutely fine. But the lines we print using Log4j eg: Log.info(“New driver instantiated”) does not get reflected in TestNG report.

Can you please explain how to print Log4j statements using TestNG. And also explain how to configure Log4j with TestNG.

Leave a Comment