Skip to content

Commit

Permalink
Initial commit. Listener works, but not ready yet to be published in …
Browse files Browse the repository at this point in the history
…central.
  • Loading branch information
zeldigas committed Aug 27, 2020
0 parents commit 331d50e
Show file tree
Hide file tree
Showing 30 changed files with 968 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.idea
*.iml

target
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased changes
### Added
- TestExecutionListener that discards all log events related to passing tests
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2020 Dmitry Pavlov

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Reasonable Test Logs

Junit5 test execution listener that hides log events for passing tests.

## Rationale

Have you ever faced with the logging noise during your project build?
Big chance you did, if your project uses some logging framework, like slf4j, and you write unit tests.

The reason is simple - logs allow you to get extra information if something goes wrong,
so there is no much sense in muting logs during tests run. At the same time we need logs, as a source of information, if
test fails and here's come the problem - there is no out of the box integration between JUnit and logging system that
can discard all logged events when tests passes and send them to configured appenders if something goes wrong.

This project aims to solve this problem providing the missing piece.

## Usage

If your codebase uses supported frameworks (see prerequisites below), just add test dependency:
```xml
<dependency>
<groupId>com.github.zeldigas</groupId>
<artifactId>reasonable-test-logs</artifactId>
<version>0.1.0</version>
<scope>test</scope>
</dependency>
```

**NB**: Jar is not available in maven central yet

### Prerequisites

#### Test engines
This project is JUnit5 only although if you have use JUnit5 as a base and have some JUnit4 tests executed via vintage
engine, it will work as well.

#### Logging frameworks
Right now only logback is supported, although it should be possible to add support for other frameworks as well (e.g. log4j2)
in case of need and requests from community.


## Examples

Check `example` directory for various test-samples. Simples way to run it, execute the following command from repo root:
```
mvn clean package
```

## Roadmap

- `0.1.0` - add test coverage for listener code, publish on maven central

## Acknowledgments
As a lot of things in our world, this project is not something unique. Once idea come to my mind,
I've googled and found out that [some folks](https://www.novatec-gmbh.de/en/blog/suppressing-logs-successful-tests/)
implemented similar ideas using JUnit4 test extension mechanism.

While it works, I found it harder to use than I want, because you need to configure such places manually or setup "catch-all" extension
in build system (e.g. surefire params for junit5).

Anyway some techniques published on [github](https://github.com/nt-ca-aqe/testit-testutils/tree/master/testutils-logsuppressor-logback)
was useful.

69 changes: 69 additions & 0 deletions example/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?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>

<parent>
<artifactId>smart-test-logs-parent</artifactId>
<groupId>com.github.zeldigas</groupId>
<version>1.0-SNAPSHOT</version>
</parent>

<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>

<artifactId>smart-test-logs-example</artifactId>
<version>1.0-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>com.github.zeldigas</groupId>
<artifactId>reasonable-test-logs</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<!-- Ignoring failures as the main idea of this module to introduce them in tests to show displayed logs -->
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</build>


</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.github.zeldigas.example.extensions;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ExtendWith(LoggingExtension.class)
public class AfterAllFailingTest {

private static final Logger log = LoggerFactory.getLogger(AfterAllFailingTest.class);

@AfterAll
public static void afterAll(){
log.info("Entering into after all that would fail");
throw new RuntimeException();
}

@Test
void hello() {
log.info("passing test");
}

@Test
void world() {

}

@Test
void failing() {
log.warn("I'm failing and should be logged");
throw new RuntimeException("Test error");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.github.zeldigas.example.extensions;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ExtendWith(LoggingExtension.class)
public class BeforeAllFailingTest {

private static final Logger log = LoggerFactory.getLogger(AfterAllFailingTest.class);

@BeforeAll
public static void beforeAll(){
log.info("Entering beforeAll that fails");
throw new RuntimeException();
}

@Test
void hello() {

}

@Test
void world() {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.github.zeldigas.example.extensions;

import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ExtendWith(LoggingExtension.class)
public class ErrorTest {

private static Logger log = LoggerFactory.getLogger(ErrorTest.class);

@BeforeAll
static void beforeAll() {
log.info("Before class");
}

@AfterAll
static void afterAll() {
log.info("After class");
}

@BeforeEach
void setUp() {
log.info("Before test");
}

@AfterEach
void tearDown() {
log.info("After test");
}

@Test
public void testFailure() {
log.info("Log in test that fails");
Assertions.assertTrue(1 == 2, "assertion failure");
}

@Test
void testError() {
log.info("Log in test that errors");
System.out.println("Result is: " + (1/0));
}

@Test
void passingTest() {
log.error("I'm passing so this message will not logged");
Assertions.assertTrue(1 == 1, "assertion failure");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.github.zeldigas.example.extensions;

public class Fixture {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.github.zeldigas.example.extensions;

import org.junit.jupiter.api.extension.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoggingExtension implements
BeforeAllCallback, BeforeEachCallback,
AfterEachCallback, AfterAllCallback,
ParameterResolver{

private Logger log = LoggerFactory.getLogger(LoggingExtension.class);

public void afterAll(ExtensionContext context) throws Exception {
log.info("After all in extension");
}

public void afterEach(ExtensionContext context) throws Exception {
log.info("After each in extension");
}

public void beforeAll(ExtensionContext context) throws Exception {
log.info("Before all in extension");
}

public void beforeEach(ExtensionContext context) throws Exception {
log.info("Before each in extension");
}

public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
return parameterContext.getParameter().getType().equals(Fixture.class);
}

public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
return new Fixture();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.github.zeldigas.example.extensions;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

@ExtendWith(LoggingExtension.class)
@Disabled
public class SkipClassTest {

@Test
public void disabledTest() {
System.out.println("I'm disabled by class");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.github.zeldigas.example.extensions;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

@ExtendWith(LoggingExtension.class)
public class SkipTest {

@Test
@Disabled
public void disabledTest() {
System.out.println("I'm disabled");
}

}
Loading

0 comments on commit 331d50e

Please sign in to comment.