Skip to content

Commit

Permalink
create surefire emulator
Browse files Browse the repository at this point in the history
  • Loading branch information
fabriciorby committed Nov 30, 2024
1 parent 68be2d7 commit 01cb89b
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package org.apache.maven.plugin.surefire;

import org.junit.jupiter.api.*;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;

import static org.junit.jupiter.api.Assertions.assertEquals;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package org.apache.maven.plugin.surefire;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package org.apache.maven.plugin.surefire;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package org.apache.maven.plugin.surefire;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package org.apache.maven.plugin.surefire;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.apache.maven.plugin.surefire.report;

import org.apache.maven.plugin.surefire.NestedExampleTest;
import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
import org.apache.maven.surefire.api.report.RunMode;
import org.apache.maven.surefire.api.report.SimpleReportEntry;
Expand All @@ -14,7 +15,7 @@
@ExtendWith(MockitoExtension.class)
class ConsoleTreeReporterTest {

//Test for NestedExampleTest
//Test for org.apache.maven.plugin.surefire.NestedExampleTest
Utf8RecodingDeferredFileOutputStream stdout = new Utf8RecodingDeferredFileOutputStream("stdout");
Utf8RecodingDeferredFileOutputStream stderr = new Utf8RecodingDeferredFileOutputStream("stderr");

Expand All @@ -27,13 +28,21 @@ static void setupContainer() throws PlexusContainerException {
logger = container.getLogger();
}

@Test
void testEmulator() {
// Now we can check the output of any Test class using this
// TODO: Add some proxy before the logger or something so we can assert the output
// TODO: Add some objects with relevant information inside the emulator
new SurefireEmulator().run(NestedExampleTest.class);
}

@Test
void testSetStarting() {
//Runs 4 times for this class
SimpleReportEntry simpleReportEntry1 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest", "Nested Sample", null, null);
SimpleReportEntry simpleReportEntry2 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest$InnerTest", "Inner Test", null, null);
SimpleReportEntry simpleReportEntry3 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest$InnerTest$InnerInnerTest", "Inner Inner Test", null, null);
SimpleReportEntry simpleReportEntry4 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest$InnerTest$InnerInnerTest$InnerInnerInnerTest", "Inner Inner Inner Test", null, null);
SimpleReportEntry simpleReportEntry1 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "org.apache.maven.plugin.surefire.NestedExampleTest", "Nested Sample", null, null);
SimpleReportEntry simpleReportEntry2 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "org.apache.maven.plugin.surefire.NestedExampleTest$InnerTest", "Inner Test", null, null);
SimpleReportEntry simpleReportEntry3 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "org.apache.maven.plugin.surefire.NestedExampleTest$InnerTest$InnerInnerTest", "Inner Inner Test", null, null);
SimpleReportEntry simpleReportEntry4 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "org.apache.maven.plugin.surefire.NestedExampleTest$InnerTest$InnerInnerTest$InnerInnerInnerTest", "Inner Inner Inner Test", null, null);

ConsoleTreeReporter consoleTreeReporter = new ConsoleTreeReporter(new PluginConsoleLogger(logger), ReporterOptions.builder().build());
consoleTreeReporter.testSetStarting(simpleReportEntry1);
Expand All @@ -46,19 +55,19 @@ void testSetStarting() {
void testSetCompleted() {

//TestStarting parameters
SimpleReportEntry simpleReportEntry1 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest", "Nested Sample", null, null);
SimpleReportEntry simpleReportEntry2 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest$InnerTest", "Inner Test", null, null);
SimpleReportEntry simpleReportEntry3 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest$InnerTest$InnerInnerTest", "Inner Inner Test", null, null);
SimpleReportEntry simpleReportEntry4 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest$InnerTest$InnerInnerTest$InnerInnerInnerTest", "Inner Inner Inner Test", null, null);
SimpleReportEntry simpleReportEntry1 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "org.apache.maven.plugin.surefire.NestedExampleTest", "Nested Sample", null, null);
SimpleReportEntry simpleReportEntry2 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "org.apache.maven.plugin.surefire.NestedExampleTest$InnerTest", "Inner Test", null, null);
SimpleReportEntry simpleReportEntry3 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "org.apache.maven.plugin.surefire.NestedExampleTest$InnerTest$InnerInnerTest", "Inner Inner Test", null, null);
SimpleReportEntry simpleReportEntry4 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "org.apache.maven.plugin.surefire.NestedExampleTest$InnerTest$InnerInnerTest$InnerInnerInnerTest", "Inner Inner Inner Test", null, null);

//Runs 1 time with all the information
//Gets all SingleReportEntries with test names and add on a list of WrapperReportEntries to create a TestSetStats
SimpleReportEntry firstTest = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest", "Nested Sample", "test", "Should pass");
SimpleReportEntry secondTest = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest", "Nested Sample", "test2", "Should pass2");
SimpleReportEntry thirdTest = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest$InnerTest", "Inner Test", "test", "Inner test should pass");
SimpleReportEntry fourthTest = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest$InnerTest$InnerInnerTest", "Inner Inner Test", "test", "Inner Inner Test should pass");
SimpleReportEntry fifthTest = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest$InnerTest$InnerInnerTest$InnerInnerInnerTest", "Inner Inner Inner Test", "test", "Inner Inner Inner Test should pass");
SimpleReportEntry sixthTest = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest$FirstInnerTest", "First Inner Test", "test", "FirstInnerTest should show up");
SimpleReportEntry firstTest = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "org.apache.maven.plugin.surefire.NestedExampleTest", "Nested Sample", "test", "Should pass");
SimpleReportEntry secondTest = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "org.apache.maven.plugin.surefire.NestedExampleTest", "Nested Sample", "test2", "Should pass2");
SimpleReportEntry thirdTest = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "org.apache.maven.plugin.surefire.NestedExampleTest$InnerTest", "Inner Test", "test", "Inner test should pass");
SimpleReportEntry fourthTest = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "org.apache.maven.plugin.surefire.NestedExampleTest$InnerTest$InnerInnerTest", "Inner Inner Test", "test", "Inner Inner Test should pass");
SimpleReportEntry fifthTest = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "org.apache.maven.plugin.surefire.NestedExampleTest$InnerTest$InnerInnerTest$InnerInnerInnerTest", "Inner Inner Inner Test", "test", "Inner Inner Inner Test should pass");
SimpleReportEntry sixthTest = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "org.apache.maven.plugin.surefire.NestedExampleTest$FirstInnerTest", "First Inner Test", "test", "FirstInnerTest should show up");

WrappedReportEntry wrappedReportEntry1 = new WrappedReportEntry(firstTest, ReportEntryType.SUCCESS, 1, stdout, stderr);
WrappedReportEntry wrappedReportEntry2 = new WrappedReportEntry(secondTest, ReportEntryType.SUCCESS, 1, stdout, stderr);
Expand All @@ -78,10 +87,12 @@ void testSetCompleted() {
TestSetStats testSetStatsForClass = new TestSetStats(false, true);

ConsoleTreeReporter consoleTreeReporter = new ConsoleTreeReporter(new PluginConsoleLogger(logger), ReporterOptions.builder().build());
//This prepares the nested tests by filling the classNames
consoleTreeReporter.testSetStarting(simpleReportEntry1);
consoleTreeReporter.testSetStarting(simpleReportEntry2);
consoleTreeReporter.testSetStarting(simpleReportEntry3);
consoleTreeReporter.testSetStarting(simpleReportEntry4);
//As soon as it finished to add tests for all the nested classes that were prepared, then it prints
consoleTreeReporter.testSetCompleted(wrappedReportEntry5, testSetStats, null);
consoleTreeReporter.testSetCompleted(wrappedReportEntry4, testSetStatsForClass, null);
consoleTreeReporter.testSetCompleted(wrappedReportEntry3, testSetStatsForClass, null);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package org.apache.maven.plugin.surefire.report;

import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
import org.apache.maven.surefire.api.report.RunMode;
import org.apache.maven.surefire.api.report.SimpleReportEntry;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.PlexusContainerException;
import org.codehaus.plexus.logging.Logger;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.platform.commons.util.StringUtils;

import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;
import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation;

public class SurefireEmulator {

Utf8RecodingDeferredFileOutputStream stdout = new Utf8RecodingDeferredFileOutputStream("stdout");
Utf8RecodingDeferredFileOutputStream stderr = new Utf8RecodingDeferredFileOutputStream("stderr");

static DefaultPlexusContainer container;
static Logger logger;
static DisplayNameGenerator displayNameGenerator;

static {
try {
container = new DefaultPlexusContainer();
logger = container.getLogger();
displayNameGenerator = DisplayNameGenerator.getDisplayNameGenerator(DisplayNameGenerator.Standard.class);
} catch (PlexusContainerException e) {
throw new RuntimeException(e);
}
}

public <T> void run(Class<T> clazz) {
TestSetStats testSetStats = new TestSetStats(false, true);
getAllMethods(getAllInnerClasses(clazz))
.entrySet().stream()
.flatMap((k) -> k.getValue().stream()
.map(i -> this.simpleReportEntryGenerator(k.getKey(), i))
.map(this::wrappedReportEntryGenerator))
.forEachOrdered(testSetStats::testSucceeded);

TestSetStats testSetStatsForClass = new TestSetStats(false, true);
ConsoleTreeReporter consoleTreeReporter = new ConsoleTreeReporter(new PluginConsoleLogger(logger), ReporterOptions.builder().build());
getAllInnerClasses(clazz).stream()
.map(this::simpleReportEntryGenerator)
.forEachOrdered(consoleTreeReporter::testSetStarting);

List<WrappedReportEntry> completedWrappedEntries =
getAllInnerClasses(clazz).stream()
.map(this::simpleReportEntryGenerator)
.map(this::wrappedReportEntryGenerator)
.collect(toList());

completedWrappedEntries.stream()
.findFirst()
.ifPresent(i -> consoleTreeReporter.testSetCompleted(i, testSetStats, null));
completedWrappedEntries.stream()
.skip(1)
.forEachOrdered(i -> consoleTreeReporter.testSetCompleted(i, testSetStatsForClass, null));
}

private <T> SimpleReportEntry simpleReportEntryGenerator(Class<T> clazz) {
return new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, clazz.getName(), getClassDisplayName(clazz), null, null);
}

private <T> SimpleReportEntry simpleReportEntryGenerator(Class<T> clazz, Method method) {
return new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, clazz.getName(), getClassDisplayName(clazz), method.getName(), getMethodDisplayName(clazz, method));
}

private WrappedReportEntry wrappedReportEntryGenerator(SimpleReportEntry simpleReportEntry) {
return new WrappedReportEntry(simpleReportEntry, ReportEntryType.SUCCESS, 1, stdout, stderr);
}

private List<Class<?>> getAllInnerClasses(Class<?> clazz) {
return getAllInnerClasses(clazz, new ArrayList<>());
}

private List<Class<?>> getAllInnerClasses(Class<?> clazz, List<Class<?>> acc) {
if (clazz.getDeclaredClasses().length == 0) {
acc.add(clazz);
return acc;
}
acc.add(clazz);
acc.addAll(Arrays.stream(clazz.getDeclaredClasses())
.flatMap(i -> getAllInnerClasses(i, new ArrayList<>()).stream())
.collect(toList()));
return acc;
}

private Map<Class<?>, List<Method>> getAllMethods(List<Class<?>> classes) {
return classes.stream()
.collect(Collectors.toMap(Function.identity(),
i -> Arrays.asList(i.getDeclaredMethods()),
(x, y) -> y, LinkedHashMap::new));
}

private String getDisplayName(AnnotatedElement element, Supplier<String> displayNameSupplier) {
Optional<DisplayName> displayNameAnnotation = findAnnotation(element, DisplayName.class);
if (displayNameAnnotation.isPresent()) {
String displayName = displayNameAnnotation.get().value().trim();
if (!StringUtils.isBlank(displayName)) return displayName;
}
return displayNameSupplier.get();
}

private <T> String getClassDisplayName(Class<T> clazz) {
if (clazz.getEnclosingClass() == null) {
return getDisplayName(clazz, () -> displayNameGenerator.generateDisplayNameForClass(clazz));
} else {
return getDisplayName(clazz, () -> displayNameGenerator.generateDisplayNameForNestedClass(clazz));
}
}

private <T> String getMethodDisplayName(Class<T> clazz, Method method) {
return getDisplayName(method, () -> displayNameGenerator.generateDisplayNameForMethod(clazz, method));
}
}

0 comments on commit 01cb89b

Please sign in to comment.