Giter Club home page Giter Club logo

suppress-logs's Introduction

Suppress Logs extension

Extension for JUnit 5 and SLF4J for temporary suppressing the error logging when error is expected, e.g. in negative tests.

What is the problem

Printing logs in tests is considered harmful - it creates much noise which can hide an actual warning. You only interested in logs of those tests which failed, all the happy ones must keep silent. Normally, this is achieved by adding logback-test.yaml or similar configuration file to your test resource folder, in which you set the log level to ERROR or WARNING, thus shutting up all the debug and info printing.

In some cases, however, your code does log at ERROR level legitimately - e.g. in an exception handler. In assertThrows tests you're getting a printout like this which clutters your build log:

Executing tasks: [:suppress-logs:test, --tests, com.github.neboskreb.suppress.logs.SuppressLogsExtensionTest.testMethodInjection] in project C:\Users\admin\Desktop\CONTRIB\log-level-control


> Task :suppress-logs:compileJava UP-TO-DATE
> Task :suppress-logs:processResources NO-SOURCE
> Task :suppress-logs:classes UP-TO-DATE
> Task :suppress-logs:compileTestJava
> Task :suppress-logs:processTestResources NO-SOURCE
> Task :suppress-logs:testClasses
> Task :suppress-logs:test
18:03:26.600 [Test worker] ERROR com.github.neboskreb.suppress.logs.BeanWithLogger -- Boom!
java.lang.Exception: You're dead!
	at com.github.neboskreb.suppress.logs.BeanWithLogger.doSomething(BeanWithLogger.java:10)
	at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:53)
	at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:35)
	at org.junit.jupiter.api.Assertions.assertThrows(Assertions.java:3115)
	at com.github.neboskreb.suppress.logs.SuppressLogsExtensionTest.testMethodInjection(SuppressLogsExtensionTest.java:23)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:728)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.api.extension.InvocationInterceptor.interceptTestMethod(InvocationInterceptor.java:119)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
	...

Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/8.4/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD SUCCESSFUL in 2s

In your case, the exception log is useless because you know that the exception is expected because you provoke it in your test. But you can't set loglevel to OFF in your logback-test.yaml because it will silence also actual warnings which you don't want to miss. It would be nice to silence the logging just for this one test.

Solution

Using @SuppressLogs annotation you can silence the logging for the duration of the test which executes the error scenario.

Getting Started

Dependency

Maven

<dependency>
    <groupId>io.github.neboskreb</groupId>
    <artifactId>suppress-logs</artifactId>
    <version>1.0.6</version>
    <scope>test</scope>
</dependency>

Gradle

dependencies {
    testImplementation 'io.github.neboskreb:suppress-logs:1.0.6'
}

Usage

Suppress Logs will find the bean under test and inspect its internals to find the logger instance. Before the test, it will set that logger to the loglevel you provided in the annotation (or "OFF" by default) and restore the original loglevel after the test finishes.

Instances of logger are looked up by the field names:

  • LOG
  • log
  • LOGGER
  • logger

Only one logger instance in the bean is expected.

Parameter injection

@ExtendWith(SuppressLogsExtension.class)
public class SuppressLogsExtensionTest {

    private final BeanWithLogger beanWithLogger = new BeanWithLogger();

    @Test
    void testParameterInjection(@SuppressLogs BeanWithLogger beanWithLogger) {
        assertThrows(Exception.class, beanWithLogger::doSomething);
    }
}

Suppress Logs extension will try to find the bean by the following logic:

  • field name matched the name of parameter
    • this can be overridden by fieldName parameter in the annotation
  • field type matches the type of the parameter

Method annotation

@ExtendWith(SuppressLogsExtension.class)
public class SuppressLogsExtensionTest {

    private final BeanWithLogger beanWithLogger = new BeanWithLogger();

    @Test
    @SuppressLogs(fieldName = "beanWithLogger")
    void testMethodInjection() {
        assertThrows(Exception.class, beanWithLogger::doSomething);
    }
}

In this case fieldName parameter is required

Thread safety

Note that because loggers are global singletons, changing their loglevel is NOT thread-safe. Your temporary change to the loglevel is effective for all tests which happen to execute that moment in parallel.

If you use Surefire plugin, you can prevent concurrent execution by annotating such tests with @NotThreadSafe. More information is found in chapter Parallel Test Execution and Single Thread Execution

Contribution

Pull requests are welcome! If you plan to open one, please first create an issue where you describe the problem/gap your contribution closes, and tag the keeper(s) of this repo so they could get back to you with help.

suppress-logs's People

Contributors

renovate[bot] avatar neboskreb avatar

Watchers

 avatar

suppress-logs's Issues

Change dependency scope to `test`

Currently, at Maven Central it shows up as production dependency:

// https://mvnrepository.com/artifact/io.github.neboskreb/suppress-logs
implementation 'io.github.neboskreb:suppress-logs:1.0.6'

Update the Maven metadata so the scope is shown as test:

// https://mvnrepository.com/artifact/io.github.neboskreb/suppress-logs
testImplementation 'io.github.neboskreb:suppress-logs:1.0.6'

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/gradle-publish.yml
  • actions/checkout v4
  • actions/setup-java v4
  • gradle/wrapper-validation-action f9c9c575b8b21b6485636a91ffecd10e558c62f6
  • gradle/gradle-build-action ac2d340dc04d9e1113182899e983b5400c17cda1
.github/workflows/gradle.yml
  • actions/checkout v4
  • actions/setup-java v4
  • gradle/actions v4.0.0@af1da67850ed9a4cedd57bfd976089dd991e2582
  • mikepenz/action-junit-report v4
  • actions/checkout v4
  • actions/setup-java v4
  • gradle/actions v4.0.0@af1da67850ed9a4cedd57bfd976089dd991e2582
gradle
gradle.properties
settings.gradle
build.gradle
integration-fixture/build.gradle
  • org.slf4j:slf4j-api 2.0.14
  • org.junit.jupiter:junit-jupiter-api 5.10.3
  • org.junit.jupiter:junit-jupiter-params 5.10.3
  • org.assertj:assertj-core 3.26.3
integration/jdk14/build.gradle
  • org.slf4j:slf4j-jdk14 2.0.14
integration/log4j/build.gradle
  • org.slf4j:slf4j-log4j12 2.0.14
integration/logback/build.gradle
  • ch.qos.logback:logback-classic 1.5.6
integration/nop/build.gradle
  • org.slf4j:slf4j-api 2.0.14
suppress-logs/build.gradle
  • org.apache.commons:commons-lang3 3.16.0
  • org.junit.jupiter:junit-jupiter-api 5.10.3
  • org.junit.jupiter:junit-jupiter-params 5.10.3
  • org.junit.jupiter:junit-jupiter-engine 5.10.3
  • org.slf4j:slf4j-api 2.0.14
  • org.slf4j:slf4j-log4j12 2.0.14
  • org.slf4j:slf4j-jdk14 2.0.14
  • ch.qos.logback:logback-classic 1.5.6
gradle-wrapper
gradle/wrapper/gradle-wrapper.properties
  • gradle 8.9

  • Check this box to trigger a request for Renovate to run again on this repository

Add integration testing

Add submodules to facilitate integration testing.

For each supported library (e.g. ch.qos.logback) add a module with simple unit test which ensures:

  • correct integration - that the target logger under the hood can be found and instrumented successfully.
  • effect - that the logs are actually suppressed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.