CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-quarkus--quarkus-junit5-internal

A runner for unit tests, intended for testing Quarkus rather than for end user consumption.

Pending
Overview
Eval results
Files

logging-test-resources.mddocs/

Logging and Test Resources

Comprehensive logging collection, filtering, and test resource management for capturing and analyzing test execution logs.

LogCollectingTestResource

A test resource that collects log records during test execution with filtering capabilities.

Core API

public class LogCollectingTestResource implements QuarkusTestResourceLifecycleManager {
    
    public static LogCollectingTestResource current();
    public List<LogRecord> getRecords();
    public void clear();
    
    // QuarkusTestResourceLifecycleManager implementation
    public void init(Map<String, String> initArgs);
    public Map<String, String> start();
    public void stop();
}

Configuration Constants

public static final String LOGGER = "logger";
public static final String LEVEL = "level";
public static final String EXCLUDE = "exclude";
public static final String INCLUDE = "include";

Utility Methods

public static String format(LogRecord record);

InMemoryLogHandler

A log handler that stores log records in memory with predicate-based filtering.

Core API

public class InMemoryLogHandler extends ExtHandler {
    
    public InMemoryLogHandler(Predicate<LogRecord> predicate);
    
    public void publish(LogRecord record);
    public void flush();
    public Level getLevel();
    public void close() throws SecurityException;
    public List<LogRecord> getRecords();
}

Usage Examples

Basic Log Collection

import io.quarkus.test.LogCollectingTestResource;
import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.QuarkusTestResource;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

@QuarkusTestResource(LogCollectingTestResource.class)
public class LoggingTest {
    
    @RegisterExtension
    static final QuarkusUnitTest config = new QuarkusUnitTest()
        .withApplicationRoot(jar -> jar.addClasses(LoggingService.class));
    
    @Test
    public void testLogging() {
        // Perform operations that generate logs
        
        // Access collected logs
        LogCollectingTestResource logResource = LogCollectingTestResource.current();
        List<LogRecord> records = logResource.getRecords();
        
        assertTrue(records.stream()
            .anyMatch(record -> record.getMessage().contains("Expected message")));
    }
}

Filtered Log Collection

@QuarkusTestResource(value = LogCollectingTestResource.class, initArgs = {
    @ResourceArg(name = LogCollectingTestResource.LOGGER, value = "org.example"),
    @ResourceArg(name = LogCollectingTestResource.LEVEL, value = "INFO"),
    @ResourceArg(name = LogCollectingTestResource.INCLUDE, value = ".*important.*")
})
public class FilteredLoggingTest {
    
    @Test
    public void testFilteredLogs() {
        LogCollectingTestResource logResource = LogCollectingTestResource.current();
        
        // Only logs from org.example logger, INFO level or above, 
        // containing "important" will be collected
        List<LogRecord> records = logResource.getRecords();
        
        records.forEach(record -> {
            assertTrue(record.getLoggerName().startsWith("org.example"));
            assertTrue(record.getLevel().intValue() >= Level.INFO.intValue());
            assertTrue(record.getMessage().contains("important"));
        });
    }
}

Exclude Pattern Log Collection

@QuarkusTestResource(value = LogCollectingTestResource.class, initArgs = {
    @ResourceArg(name = LogCollectingTestResource.EXCLUDE, value = ".*debug.*|.*trace.*")
})
public class ExcludePatternLoggingTest {
    
    @Test
    public void testExcludePattern() {
        LogCollectingTestResource logResource = LogCollectingTestResource.current();
        List<LogRecord> records = logResource.getRecords();
        
        // No debug or trace messages should be collected
        records.forEach(record -> {
            assertFalse(record.getMessage().toLowerCase().contains("debug"));
            assertFalse(record.getMessage().toLowerCase().contains("trace"));
        });
    }
}

Manual Log Handler Usage

import io.quarkus.test.InMemoryLogHandler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

public class ManualLogHandlerTest {
    
    @Test
    public void testInMemoryLogHandler() {
        // Create handler with predicate
        InMemoryLogHandler handler = new InMemoryLogHandler(
            record -> record.getLevel().intValue() >= Level.WARNING.intValue()
        );
        
        // Add to logger
        Logger logger = Logger.getLogger("test.logger");
        logger.addHandler(handler);
        
        try {
            // Generate logs
            logger.info("This will be filtered out");
            logger.warning("This will be captured");
            logger.severe("This will also be captured");
            
            // Check captured records
            List<LogRecord> records = handler.getRecords();
            assertEquals(2, records.size());
            
            assertTrue(records.stream()
                .allMatch(record -> record.getLevel().intValue() >= Level.WARNING.intValue()));
                
        } finally {
            logger.removeHandler(handler);
            handler.close();
        }
    }
}

Log Formatting

@Test
public void testLogFormatting() {
    LogCollectingTestResource logResource = LogCollectingTestResource.current();
    
    // Generate a log record
    // ...
    
    List<LogRecord> records = logResource.getRecords();
    LogRecord record = records.get(0);
    
    // Format the log record
    String formatted = LogCollectingTestResource.format(record);
    
    // Use formatted output for assertions or debugging
    System.out.println("Formatted log: " + formatted);
}

Clearing Logs Between Tests

public class MultipleTestsWithLogging {
    
    @Test
    public void testFirst() {
        LogCollectingTestResource logResource = LogCollectingTestResource.current();
        
        // Perform test operations
        // ...
        
        // Verify logs
        List<LogRecord> records = logResource.getRecords();
        assertFalse(records.isEmpty());
        
        // Clear logs for next test
        logResource.clear();
    }
    
    @Test
    public void testSecond() {
        LogCollectingTestResource logResource = LogCollectingTestResource.current();
        
        // Logs from previous test should not be present
        List<LogRecord> records = logResource.getRecords();
        assertTrue(records.isEmpty());
        
        // Perform new test operations
        // ...
    }
}

Complex Log Analysis

@Test
public void testComplexLogAnalysis() {
    LogCollectingTestResource logResource = LogCollectingTestResource.current();
    
    // Perform operations that generate various logs
    // ...
    
    List<LogRecord> records = logResource.getRecords();
    
    // Analyze log patterns
    Map<Level, Long> logsByLevel = records.stream()
        .collect(Collectors.groupingBy(
            LogRecord::getLevel,
            Collectors.counting()
        ));
    
    // Verify log distribution
    assertTrue(logsByLevel.get(Level.INFO) > 0);
    assertEquals(0, logsByLevel.getOrDefault(Level.SEVERE, 0L));
    
    // Check log sequence
    List<String> messages = records.stream()
        .map(LogRecord::getMessage)
        .collect(Collectors.toList());
    
    assertTrue(messages.indexOf("Operation started") < 
               messages.indexOf("Operation completed"));
    
    // Verify logger names
    Set<String> loggerNames = records.stream()
        .map(LogRecord::getLoggerName)
        .collect(Collectors.toSet());
    
    assertTrue(loggerNames.contains("org.example.MyService"));
}

Configuration Options

Logger Configuration

  • LOGGER: Specify which logger to capture (e.g., "org.example", "ROOT")
  • LEVEL: Minimum log level to capture (e.g., "DEBUG", "INFO", "WARN", "ERROR")

Pattern Filtering

  • INCLUDE: Regex pattern for messages to include
  • EXCLUDE: Regex pattern for messages to exclude

Example Configuration

@QuarkusTestResource(value = LogCollectingTestResource.class, initArgs = {
    @ResourceArg(name = "logger", value = "org.example.MyService"),
    @ResourceArg(name = "level", value = "DEBUG"),
    @ResourceArg(name = "include", value = ".*transaction.*|.*request.*"),
    @ResourceArg(name = "exclude", value = ".*heartbeat.*")
})

This configuration will:

  • Only capture logs from "org.example.MyService" logger
  • Include DEBUG level and above
  • Only include messages containing "transaction" or "request"
  • Exclude any messages containing "heartbeat"

Install with Tessl CLI

npx tessl i tessl/maven-io-quarkus--quarkus-junit5-internal

docs

build-chain-customization.md

dev-mode-testing.md

index.md

logging-test-resources.md

prod-mode-testing.md

results-utilities.md

unit-testing.md

tile.json