1 year ago

#73882

test-img

CHANist

Logging each JUnit test on different log file in multi-thread environment

I would like to create a log for each JUnit Test I have run, each having its own file.

Actually, I have done that yesterday, with the help of Logback's SiftingAppender.

import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

public class CustomJUnitTestRule implements AfterEachCallback, BeforeEachCallback {

    @Override
    public void beforeEach(ExtensionContext extensionContext) throws Exception {
        Class<?> testClass = extensionContext.getTestClass().get();
        AnnotatedElement annotatedElement = extensionContext.getElement().get();
        Method method = extensionContext.getTestMethod().get();
        String methodName = method.getName();
        DisplayName displayName = testClass.getAnnotation(DisplayName.class);
        String topic = displayName.value();
        boolean annotationPresent = annotatedElement.isAnnotationPresent(Order.class);
        int order = -1;
        if (annotationPresent) {
            Order orderAnnotation = annotatedElement.getAnnotation(Order.class);
            order = orderAnnotation.value();
        }
        String fileName = String.format("%s-%02d-%s", topic, order, methodName);
        MDC.put("testId", fileName);
    }

    @Override
    public void afterEach(ExtensionContext extensionContext) throws Exception {
        MDC.remove("testId");
    }
}

with a sample logback.xml

<configuration>

  <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
    <!-- in the absence of the class attribute, it is assumed that the
         desired discriminator type is
         ch.qos.logback.classic.sift.MDCBasedDiscriminator -->
    <discriminator>
      <key>testId</key>
      <defaultValue>unknown</defaultValue>
    </discriminator>
    <sift>
      <appender name="FILE-${userid}" class="ch.qos.logback.core.FileAppender">
        <file>${testId}.log</file>
        <append>false</append>
        <layout class="ch.qos.logback.classic.PatternLayout">
          <pattern>%d [%thread] %level %mdc %logger{35} - %msg%n</pattern>
        </layout>
      </appender>
    </sift>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="SIFT" />
  </root>
</configuration>

and a simple test

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@DisplayName("abc")
public class ABCTest {
    @Test
    @Order(1)
    public void xxxTest() {
        // ...
    }
}

It is working as intended at the first sight.

However as it uses MDC to work in the background, which essentially is thread bounded, which makes some of my unit test, which creates multiple thread, not working as intended.

Can I create a logback's appender, which is not MDC bound, but globally, so that all logs in different threads (other than thread running jUnit test case), can be found in the log file as well?

java

multithreading

junit

sifting-appender

0 Answers

Your Answer

Accepted video resources