How to use Log4j in Selenium WebDriver

How to use Log4j in Selenium WebDriver

In this article, you will learn how to use Log4j in your Selenium WebDriver tests. Log4j makes it possible to add logging in your Selenium tests.

Table of contents

What is Log4j?

Log4j is a Java-based logging utility. As of this writing, Apache Log4j 2.x is the latest version for Log4j and it provides significant improvements over its predecessor, Log4j 1.x.

How to get started

There are four ways to configure Log4j.

  1. Through a configuration file written in XML, JSON, YAML, or properties format.
  2. By creating a ConfigurationFactory and Configuration implementation. (programmatically)
  3. By calling the APIs exposed in the Configuration interface to add components to the default configuration. (programmatically)
  4. By calling methods on the internal Logger class. (programmatically)

In this tutorial, we’re going to be using option one with a properties configuration file.

The properties file

The properties file may contain various components including a logger, filter and appender. Furthermore,

  • Each individual component must have a type attribute specified that identifies the component’s Plugin type.
  • The logger element must have a name attribute specified, will usually have a level attribute specified and may also have an additivity attribute specified.
  • You can use TRACE, DEBUG, INFO, WARN, ERROR, ALL or OFF to configure the level. If no level is specified it will default to ERROR.
  • You may assign a true or false value to the additivity attribute. Omitting the attribute will cause the default value of true to be used.
  • Every configuration must have a root logger. If one is not provided, LoggerConfig will be used by default. LoggerConfig has a level of ERROR and a Console appender attached. The main differences between the root logger and other loggers are:
    • The root logger does not have a name attribute.
    • The root logger does not support the additivity attribute since it has no parent.

Don’t worry if any or all of this doesn’t make sense now. It will all start making more and more sense the more you work with Log4j.

Creating a Maven project

If you are using IntelliJ IDEA, go to File > New > Project > Select Maven > Click Next > Give project a name > Click Finish.

Java Maven project setup
Naming a Maven project

Adding dependencies

Lets begin by adding the Selenium and TestNG dependencies.

Click here for the latest dependency versions and add them to your pom.xml file.

Selenium and TestNG dependencies in MVN Repository website
Selenium Java Maven

Next, we need to add the Log4j dependencies.

Log4j consists of an API and an implementation (Core). You will need to add both dependencies to your pom.xml file. Make sure that you select Apache Log4j Core and Apache Log4j API dependencies and not the Apache Log4j dependency (this is the old Log4j 1.x version).

Log4j2 dependencies in MVN Repository website

By now, your pom.xml file should look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Log4j2Example</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>

        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>7.1.0</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>7.1.0</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.13.3</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.13.3</version>
        </dependency>
    </dependencies>
</project>

Properties file creation

log4j2 properties file in a Maven project

Log4j expects the properties file to be located under src > main > resources in your project and the file must be named log4j2.properties.

Add the following properties to log messages to the console.

# configuration syntax
status=error
dest=err
name=PropertiesConfig

# publish console logs
appender.console.type=Console
appender.console.name=STDOUT
appender.console.layout.type=PatternLayout
appender.console.layout.pattern=[%-5level] %d{DEFAULT} %c:%L - %m%n

# capture logs
logger.app.name=base
logger.app.level=debug
logger.app.additivity=false
logger.app.appenderRef.console.ref=STDOUT

# root logger
rootLogger.level=info
rootLogger.appenderRef.stdout.ref=STDOUT

Base class creation

Maven project's base class

Add a new package under src > main > java called base. Create a class called BaseClass inside this package. Now, add a WebDriver and Logger instance making sure that the Logger is imported from the org.apache.logging.log4j class.

Log4j logger import

Lastly, add a setUp and tearDown method to the BaseClass with some logging statements as follows.

package base;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;

public class BaseClass {
    public static WebDriver driver;
    public static Logger log = LogManager.getLogger();

    @BeforeSuite
    public void setUp() {
        if (driver == null) {
            log.info("Hello World!");
        }
    }

    @AfterSuite
    public void tearDown() {
        log.info("Goodbye!");
        if (driver != null) {
            driver.quit();
        }
    }
}

Your first test

HelloWorld class in a Maven project

Add a new package under src > test > java called com.automation.testcases. Next, create a HelloWorld class in this package.

Create a test called test testHelloWorld and add several logging statements as follows.

package com.automation.testcases;

import base.BaseClass;
import org.testng.annotations.Test;

public class HelloWorld extends BaseClass {

    @Test
    public void testHelloWorld() {
        log.debug("Sample DEBUG message");
        log.error("Sample ERROR message");
        log.info("Sample INFO message");
        log.warn("Sample WARN message");
    }
}

TestNG run configuration

To begin, right-click the HelloWorld class and select Create ‘HelloWorld‘.

TestNG run configuration setup

Next, give your configuration a name. Make sure that Class is selected as the Test kind value. Then, click OK.

TestNG run configuration setup

After that, click the green play button to run your newly created configuration.

IntelliJ Run button

As a result, the console output should look something like this:

console output

Congratulations! You have successfully configures Log4j with your Selenium project.

Exporting logs to a file

This is great but what if you want to export the logs to a file?

To log messages to a file, simply add a new appender to the properties file of type File with a corresponding logger (logger.app.appenderRef.file.ref). The updated log4j2.properties file should be as follows.

# configuration syntax
status=error
dest=err
name=PropertiesConfig

# publish console logs
appender.console.type=Console
appender.console.name=STDOUT
appender.console.layout.type=PatternLayout
appender.console.layout.pattern=[%-5level] %d{DEFAULT} %c:%L - %m%n

# publish file logs
appender.file.type=File
appender.file.name=LOGFILE
appender.file.fileName=logs/myLog.log
appender.file.layout.type=PatternLayout
appender.file.layout.pattern=[%-5level] %d{DEFAULT} %c:%L - %m%n
appender.file.append=false

# capture logs
logger.app.name=base
logger.app.level=debug
logger.app.additivity=false
logger.app.appenderRef.console.ref=STDOUT
logger.app.appenderRef.file.ref=LOGFILE

# root logger
rootLogger.level=info
rootLogger.appenderRef.stdout.ref=STDOUT

Re-run the test. As a result, this creates a new folder called logs. This folder will contain a file called myLog.log. This log file will have the same log statements that were printed to the console.

log4j log file

Now you know how to use Log4j in your Selenium WebDriver tests.

If you feel that you haven’t had enough yet, read on! Next, we’ll dive deeper into the contents of the properties file by looking at one line at a time.

Properties file in detail

status – The level of internal Log4j events that should be logged to the console. Valid values for this attribute are “trace”, “debug”, “info”, “warn”, “error” and “fatal”. Log4j will log details about initialization, rollover and other internal actions to the status logger. Setting status=”trace” is one of the first tools available to you if you need to troubleshoot log4j.

dest – Accepts either “err” for stderr, “out” for stdout, a file path, or a URL.

name – The name of the configuration.

appender.console.type=Console – The appender which publish logs to the console.

appender.console.name=STDOUT – The name of the console appender. This can be any name you choose.

appender.console.layout.type=PatternLayout – An Appender uses a Layout to format a LogEvent into a form that meets the needs of whatever will be consuming the log event. Click here to learn more about PatterLayout.

appender.console.layout.pattern=[%-5level] %d{DEFAULT} %c:%L – %m%n – Let’s break this down

  • %-5level = by default the amount of space allocated for the log level will be 5 characters, the “-“ me means it will be left-aligned
  • %d{DEFAULT} = default date format (example: 2020-01-01 15:00:00,123)
  • %c = Outputs the name of the logger that published the logging event
  • %L = Outputs the line number from where the logging request was issued
  • %m = Outputs the application supplied message associated with the logging event
  • %n = Outputs the platform dependent line separator character or characters

appender.file.append – Whether or not you wish to keep adding to the same file or create a new one each time the test runs.

logger.app.name=base – Refers to the name of the package where the Logger is located.

logger.app.level=debug – Sets the Logger’s LogLevel to DEBUG.

logger.app.additivity=false – Disables additivity
Click here to learn more.

logger.app.appenderRef.console.ref=STDOUT – The name of the Console appender as entered in appender.console.name (the names must match).

logger.app.appenderRef.file.ref=LOGFILE – The name of the File appender as entered in appender.file.name (the names must match).

rootLogger.level=info – Sets the rootLogger’s LogLevel to INFO

rootLogger.appenderRef.stdout.ref=STDOUT – Specified the rootLogger’s appender as entered in appender.console.name or appender.file.name (the names must match).

References

Log4j documentation

Leave a Reply