From 44931dca44a2bfd1761e6033b8a1145caabe835d Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Mon, 16 Oct 2023 16:56:20 +0200 Subject: [PATCH] Include all failing test classes in AOT end-to-end test report Prior to this commit, AotIntegrationTests only printed "failing test classes" for tests that failed at the class level. This commit updates the reporting logic to report test classes for failing test methods as well. Current results for the spring-test module: Test run finished after 6531 ms [ 403 containers found ] [ 27 containers skipped ] [ 376 containers started ] [ 0 containers aborted ] [ 366 containers successful ] [ 10 containers failed ] [ 757 tests found ] [ 61 tests skipped ] [ 689 tests started ] [ 9 tests aborted ] [ 585 tests successful ] [ 95 tests failed ] Failing Test Classes: org.springframework.test.context.configuration.interfaces.ContextHierarchyInterfaceTests org.springframework.test.context.configuration.interfaces.SqlConfigInterfaceTests org.springframework.test.context.expression.ExpressionUsageTests org.springframework.test.context.groovy.AbsolutePathGroovySpringContextTests org.springframework.test.context.groovy.GroovySpringContextTests org.springframework.test.context.groovy.RelativePathGroovySpringContextTests org.springframework.test.context.hierarchies.meta.MetaHierarchyLevelTwoTests org.springframework.test.context.hierarchies.standard.ClassHierarchyWithMergedConfigLevelOneTests org.springframework.test.context.hierarchies.standard.ClassHierarchyWithMergedConfigLevelTwoTests org.springframework.test.context.hierarchies.standard.ClassHierarchyWithOverriddenConfigLevelTwoTests org.springframework.test.context.hierarchies.standard.DirtiesContextWithContextHierarchyTests org.springframework.test.context.hierarchies.standard.SingleTestClassWithTwoLevelContextHierarchyAndMixedConfigTypesTests org.springframework.test.context.hierarchies.standard.SingleTestClassWithTwoLevelContextHierarchyTests org.springframework.test.context.hierarchies.standard.TestHierarchyLevelTwoWithBareContextConfigurationInSubclassTests org.springframework.test.context.hierarchies.standard.TestHierarchyLevelTwoWithBareContextConfigurationInSuperclassTests org.springframework.test.context.hierarchies.standard.TestHierarchyLevelTwoWithSingleLevelContextHierarchyAndMixedConfigTypesTests org.springframework.test.context.hierarchies.standard.TestHierarchyLevelTwoWithSingleLevelContextHierarchyTests org.springframework.test.context.hierarchies.web.ControllerIntegrationTests org.springframework.test.context.hierarchies.web.DispatcherWacRootWacEarTests org.springframework.test.context.hierarchies.web.RootWacEarTests org.springframework.test.context.jdbc.CustomScriptSyntaxSqlScriptsTests org.springframework.test.context.jdbc.GlobalCustomScriptSyntaxSqlScriptsTests org.springframework.test.context.jdbc.InferredDataSourceTransactionalSqlScriptsTests org.springframework.test.context.jdbc.InfrastructureProxyTransactionalSqlScriptsTests org.springframework.test.context.jdbc.MultipleDataSourcesAndTransactionManagersSqlScriptsTests org.springframework.test.context.jdbc.MultipleDataSourcesAndTransactionManagersTransactionalSqlScriptsTests org.springframework.test.context.jdbc.NonTransactionalSqlScriptsTests org.springframework.test.context.jdbc.RepeatableSqlAnnotationSqlScriptsChildTests org.springframework.test.context.jdbc.RepeatableSqlAnnotationSqlScriptsParentTests org.springframework.test.context.jdbc.TransactionalAfterTestMethodSqlScriptsTests org.springframework.test.context.jdbc.TransactionalInlinedStatementsSqlScriptsTests org.springframework.test.context.junit.jupiter.nested.ContextHierarchyNestedTests$NestedTestCaseWithInheritedConfigTests org.springframework.test.context.junit.jupiter.nested.ContextHierarchyNestedTests$NestedTestCaseWithInheritedConfigTests$DoubleNestedTestCaseWithOverriddenConfigTests org.springframework.test.context.junit.jupiter.nested.ContextHierarchyNestedTests$NestedTestCaseWithInheritedConfigTests$DoubleNestedTestCaseWithOverriddenConfigTests$TripleNestedWithInheritedConfigAndTestInterfaceTests org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$ConfigOverriddenByDefaultTests org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$InheritedAndExtendedConfigTests org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$InheritedAndExtendedConfigTests$DoubleNestedWithOverriddenConfigTests org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$InheritedAndExtendedConfigTests$DoubleNestedWithOverriddenConfigTests$TripleNestedWithInheritedConfigAndTestInterfaceTests org.springframework.test.context.junit.jupiter.orm.JpaEntityListenerTests org.springframework.test.context.junit4.AbsolutePathSpringJUnit4ClassRunnerAppCtxTests org.springframework.test.context.junit4.ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests org.springframework.test.context.junit4.ConcreteTransactionalJUnit4SpringContextTests org.springframework.test.context.junit4.InheritedConfigSpringJUnit4ClassRunnerAppCtxTests org.springframework.test.context.junit4.MultipleResourcesSpringJUnit4ClassRunnerAppCtxTests org.springframework.test.context.junit4.ParameterizedDependencyInjectionTests org.springframework.test.context.junit4.RelativePathSpringJUnit4ClassRunnerAppCtxTests org.springframework.test.context.junit4.SpringJUnit4ClassRunnerAppCtxTests org.springframework.test.context.junit4.annotation.AnnotationConfigSpringJUnit4ClassRunnerAppCtxTests org.springframework.test.context.junit4.rules.TransactionalSqlScriptsSpringRuleTests org.springframework.test.context.junit4.spr9799.Spr9799XmlConfigTests org.springframework.test.context.testng.ConcreteTransactionalTestNGSpringContextTests org.springframework.test.context.testng.transaction.ejb.CommitForRequiredEjbTxDaoTestNGTests org.springframework.test.context.testng.transaction.ejb.CommitForRequiresNewEjbTxDaoTestNGTests org.springframework.test.context.testng.transaction.ejb.RollbackForRequiredEjbTxDaoTestNGTests org.springframework.test.context.testng.transaction.ejb.RollbackForRequiresNewEjbTxDaoTestNGTests org.springframework.test.context.transaction.ejb.CommitForRequiredEjbTxDaoTests org.springframework.test.context.transaction.ejb.CommitForRequiresNewEjbTxDaoTests org.springframework.test.context.transaction.ejb.RollbackForRequiredEjbTxDaoTests org.springframework.test.context.transaction.ejb.RollbackForRequiresNewEjbTxDaoTests org.springframework.test.web.servlet.samples.client.context.JavaConfigTests org.springframework.test.web.servlet.samples.client.context.WebAppResourceTests org.springframework.test.web.servlet.samples.client.context.XmlConfigTests org.springframework.test.web.servlet.samples.context.JavaConfigTests org.springframework.test.web.servlet.samples.context.WebAppResourceTests org.springframework.test.web.servlet.samples.context.XmlConfigTests See gh-29122 --- .../test/context/aot/AotIntegrationTests.java | 49 ++++++++++++++----- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/AotIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/AotIntegrationTests.java index 93efd431cc2e..b79117a0bcc9 100644 --- a/spring-test/src/test/java/org/springframework/test/context/aot/AotIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/aot/AotIntegrationTests.java @@ -26,8 +26,10 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.junit.platform.engine.TestSource; import org.junit.platform.engine.discovery.ClassNameFilter; import org.junit.platform.engine.support.descriptor.ClassSource; +import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; @@ -176,18 +178,7 @@ private static void runTestsInAotMode(long expectedNumTests, List> test summary.printTo(new PrintWriter(System.err)); } if (summary.getTotalFailureCount() > 0) { - System.err.println("Failing Test Classes:"); - summary.getFailures().stream() - .map(Failure::getTestIdentifier) - .map(TestIdentifier::getSource) - .flatMap(Optional::stream) - .filter(ClassSource.class::isInstance) - .map(ClassSource.class::cast) - .map(AotIntegrationTests::getJavaClass) - .flatMap(Optional::stream) - .map(Class::getName) - .forEach(System.err::println); - System.err.println(); + printFailingTestClasses(summary); List exceptions = summary.getFailures().stream().map(Failure::getException).toList(); throw new MultipleFailuresError("Test execution failures", exceptions); } @@ -200,6 +191,30 @@ private static void runTestsInAotMode(long expectedNumTests, List> test } } + private static void printFailingTestClasses(TestExecutionSummary summary) { + System.err.println("Failing Test Classes:"); + summary.getFailures().stream() + .map(Failure::getTestIdentifier) + .map(TestIdentifier::getSource) + .flatMap(Optional::stream) + .map(TestSource.class::cast) + .map(source -> { + if (source instanceof ClassSource classSource) { + return getJavaClass(classSource); + } + else if (source instanceof MethodSource methodSource) { + return getJavaClass(methodSource); + } + return Optional.> empty(); + }) + .flatMap(Optional::stream) + .map(Class::getName) + .distinct() + .sorted() + .forEach(System.err::println); + System.err.println(); + } + private static Optional> getJavaClass(ClassSource classSource) { try { return Optional.of(classSource.getJavaClass()); @@ -210,6 +225,16 @@ private static Optional> getJavaClass(ClassSource classSource) { } } + private static Optional> getJavaClass(MethodSource methodSource) { + try { + return Optional.of(methodSource.getJavaClass()); + } + catch (Exception ex) { + // ignore exception + return Optional.empty(); + } + } + private static TestClassScanner createTestClassScanner() { String classpathRoot = System.getProperty(CLASSPATH_ROOT); assertThat(classpathRoot).as(CLASSPATH_ROOT).isNotNull();