Set file name to the testNG class name for log4j2?

Viewed 825

I am developing an automation framework for which I am using slf4j (version 1.7.21).

I want to be able to write every test class's logs into its own file. I am new to log4j2 and this is what I have tried so far.

I read that to set the file name dynamically, we should set a system property in a static block in my class and then use this property to set the file name in my log4j2-test.xml.

This is how my class looks like :

public class TestClass {
    Logger log;
    static {
        System.setProperty("logFilename", "TestClass");
        log = LoggerFactory.getLogger(TestClass.class);
    }

    @Test
    public static void testLogger() {
        log.info("Testing logger");
    }
}

My log4j2.xml looks like :

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" name="Regressions">
<Properties>
    <Property name="logs.dir">logs</Property>
    <Property name="pattern">%d %-5p - [%logger] ~ %m (%c{1.}:%L)%n</Property>
</Properties>

<Appenders>
    <Console name="Console" target="SYSTEM_OUT">
        <PatternLayout pattern="${pattern}"/>
    </Console>
    <File name="All" fileName="${sys:logs.dir}/${sys:logFilename}.log" append="false">
        <PatternLayout pattern="${pattern}"/>
    </File>
    <File name="Debug" fileName="${sys:logs.dir}/${sys:logFilename}-DEBUG.log" append="false">
        <PatternLayout pattern="${pattern}"/>
    </File>
    <File name="Error" fileName="${sys:logs.dir}/${sys:logFilename}-ERROR.log" append="false">
        <PatternLayout pattern="${pattern}"/>
    </File>
</Appenders>
<Loggers>
    <Logger name="org.apache.http" level="DEBUG" additivity="false">
        <AppenderRef ref="Debug"/>
    </Logger>
    <Root level="info">
        <AppenderRef ref="Console"/>
        <AppenderRef ref="All"/>
    </Root>
</Loggers>

This works well when I have the static block in each test class.

Now, I want to do this in a base test class. Here is where the issue lies. I tried the following things :

1) Get the class name in the base class :

public class BaseClass {
    String testClass = this.getClass().getSimpleName();
}

But as it is a static block, I can't call this.

2) Another way is to have a separate method in the base class to create the logger :

public class TestClass {
    Logger log = BaseClass.getLogger(TestClass.class);
}

public class BaseClass {
    public static Logger getLogger (Class className) { 
        System.setProperty("logFilename", className.getSimpleName());
        return LoggerFactory.getLogger(className);
    }
}

which I find ugly. Is there a better way to do it?

0 Answers
Related