Support navigation to failed tests in @⁠Inject TCK tests

See gh-35126
This commit is contained in:
Sam Brannen 2025-06-29 15:55:07 +02:00
parent ed86daa080
commit ec16b03949
1 changed files with 20 additions and 32 deletions

View File

@ -16,14 +16,11 @@
package org.springframework.context.annotation.jsr330; package org.springframework.context.annotation.jsr330;
import java.util.Enumeration; import java.net.URI;
import java.util.Spliterator; import java.util.Collections;
import java.util.Spliterators;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import junit.framework.TestCase; import junit.framework.TestCase;
import junit.framework.TestFailure;
import junit.framework.TestResult; import junit.framework.TestResult;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.atinject.tck.Tck; import org.atinject.tck.Tck;
@ -44,6 +41,7 @@ import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.context.annotation.Jsr330ScopeMetadataResolver; import org.springframework.context.annotation.Jsr330ScopeMetadataResolver;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.context.support.GenericApplicationContext; import org.springframework.context.support.GenericApplicationContext;
import org.springframework.util.ClassUtils;
import static org.junit.jupiter.api.DynamicContainer.dynamicContainer; import static org.junit.jupiter.api.DynamicContainer.dynamicContainer;
import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.DynamicTest.dynamicTest;
@ -61,7 +59,8 @@ class SpringAtInjectTckTests {
@TestFactory @TestFactory
Stream<? extends DynamicNode> runTechnologyCompatibilityKit() { Stream<? extends DynamicNode> runTechnologyCompatibilityKit() {
TestSuite testSuite = (TestSuite) Tck.testsFor(buildCar(), false, true); TestSuite testSuite = (TestSuite) Tck.testsFor(buildCar(), false, true);
return generateDynamicTests(testSuite); Class<?> suiteClass = resolveTestSuiteClass(testSuite);
return generateDynamicTests(testSuite, suiteClass);
} }
@ -84,45 +83,34 @@ class SpringAtInjectTckTests {
return ac.getBean(Car.class); return ac.getBean(Car.class);
} }
private static Stream<? extends DynamicNode> generateDynamicTests(TestSuite testSuite) { private static Stream<? extends DynamicNode> generateDynamicTests(TestSuite testSuite, Class<?> suiteClass) {
return stream(testSuite.tests()).map(test -> { return Collections.list(testSuite.tests()).stream().map(test -> {
if (test instanceof TestSuite nestedSuite) { if (test instanceof TestSuite nestedSuite) {
return dynamicContainer(nestedSuite.getName(), generateDynamicTests(nestedSuite)); Class<?> nestedSuiteClass = resolveTestSuiteClass(nestedSuite);
URI uri = URI.create("class:" + nestedSuiteClass.getName());
return dynamicContainer(nestedSuite.getName(), uri, generateDynamicTests(nestedSuite, nestedSuiteClass));
} }
if (test instanceof TestCase testCase) { if (test instanceof TestCase testCase) {
return dynamicTest(testCase.getName(), () -> runTestCase(testCase)); URI uri = URI.create("method:" + suiteClass.getName() + "#" + testCase.getName());
return dynamicTest(testCase.getName(), uri, () -> runTestCase(testCase));
} }
throw new IllegalStateException("Unsupported Test type: " + test.getClass().getName()); throw new IllegalStateException("Unsupported Test type: " + test.getClass().getName());
}); });
} }
private static void runTestCase(TestCase testCase) { private static void runTestCase(TestCase testCase) throws Throwable {
TestResult testResult = new TestResult(); TestResult testResult = new TestResult();
testCase.run(testResult); testCase.run(testResult);
assertSuccessfulResults(testResult); if (testResult.failureCount() > 0) {
} throw testResult.failures().nextElement().thrownException();
}
private static void assertSuccessfulResults(TestResult testResult) { if (testResult.errorCount() > 0) {
if (!testResult.wasSuccessful()) { throw testResult.errors().nextElement().thrownException();
Throwable throwable = Stream.concat(stream(testResult.failures()), stream(testResult.errors()))
.map(TestFailure::thrownException)
.findFirst()
.get();
if (throwable instanceof Error error) {
throw error;
}
if (throwable instanceof RuntimeException runtimeException) {
throw runtimeException;
}
throw new AssertionError(throwable);
} }
} }
private static <T> Stream<T> stream(Enumeration<T> enumeration) { private static Class<?> resolveTestSuiteClass(TestSuite testSuite) {
Spliterator<T> spliterator = Spliterators.spliteratorUnknownSize( return ClassUtils.resolveClassName(testSuite.getName(), Tck.class.getClassLoader());
enumeration.asIterator(), Spliterator.ORDERED);
return StreamSupport.stream(spliterator, false);
} }
} }