Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 0 additions & 49 deletions java-reporter-junit/debug_test.java

This file was deleted.

7 changes: 3 additions & 4 deletions java-reporter-junit/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>io.testomat</groupId>
<artifactId>java-reporter-junit</artifactId>
<version>0.6.8</version>
<version>0.7.2</version>
<packaging>jar</packaging>

<name>Testomat.io Java Reporter JUnit</name>
Expand Down Expand Up @@ -49,7 +49,7 @@
<dependency>
<groupId>io.testomat</groupId>
<artifactId>java-reporter-core</artifactId>
<version>0.6.8</version>
<version>0.7.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
Expand All @@ -61,8 +61,7 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.8.0</version>
<scope>provided</scope>
<version>${junit.version}</version>
<optional>true</optional>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import io.testomat.core.exception.NoMethodInContextException;
import io.testomat.core.model.TestMetadata;
import io.testomat.junit.extractor.strategy.ParameterExtractorService;
import io.testomat.junit.util.ParameterizedTestSupport;
import java.lang.reflect.Method;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;

/**
* Extracts metadata and parameters from JUnit test methods.
Expand Down Expand Up @@ -68,7 +68,7 @@ public Object extractTestParameters(ExtensionContext context) {
public boolean isParameterizedTest(ExtensionContext context) {
try {
Method method = context.getTestMethod().orElse(null);
return method != null && method.isAnnotationPresent(ParameterizedTest.class);
return ParameterizedTestSupport.isParameterizedTest(method);
} catch (Exception e) {
return false;
}
Expand All @@ -81,9 +81,19 @@ private String buildTestTitle(Method method, ExtensionContext context) {
return titleFromAnnotation;
}

ParameterizedTest parameterized = method.getAnnotation(ParameterizedTest.class);
if (parameterized != null) {
return buildParameterizedTitle(method, parameterized);
// Check for ParameterizedTest annotation using reflection
if (ParameterizedTestSupport.isParameterizedTest(method)) {
ParameterizedTestSupport.loadAnnotationClass("ParameterizedTest")
.ifPresent(parameterizedTestClass -> {
try {
Object parameterized = method.getAnnotation(parameterizedTestClass);
if (parameterized != null) {
buildParameterizedTitle(method, parameterized);
}
} catch (Exception e) {
// Ignore reflection errors
}
});
}

return method.getName();
Expand All @@ -92,12 +102,18 @@ private String buildTestTitle(Method method, ExtensionContext context) {
}
}

private String buildParameterizedTitle(Method method, ParameterizedTest parameterized) {
String customName = parameterized.name();
if (isCustomNameProvided(customName)) {
private String buildParameterizedTitle(Method method, Object parameterized) {
try {
// Use reflection to safely access the name() method
java.lang.reflect.Method nameMethod = parameterized.getClass().getMethod("name");
String customName = (String) nameMethod.invoke(parameterized);
if (isCustomNameProvided(customName)) {
return method.getName();
}
return method.getName();
} catch (Exception e) {
return method.getName();
}
return method.getName();
}

private boolean isCustomNameProvided(String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,11 @@
import io.testomat.junit.extractor.strategy.handlers.NullSourceHandler;
import io.testomat.junit.extractor.strategy.handlers.ParameterExtractionHandler;
import io.testomat.junit.extractor.strategy.handlers.ValueSourceHandler;
import io.testomat.junit.util.ParameterizedTestSupport;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.junit.jupiter.params.provider.CsvFileSource;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.EmptySource;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.NullAndEmptySource;
import org.junit.jupiter.params.provider.NullSource;
import org.junit.jupiter.params.provider.ValueSource;

/**
* Registry that maintains direct mapping between JUnit parameter source annotations
Expand Down Expand Up @@ -64,14 +56,19 @@ public ParameterHandlerRegistry(Map<Class<? extends Annotation>,
* @throws IllegalStateException if multiple conflicting handlers are found
*/
public Optional<ParameterExtractionHandler> findHandler(ParameterExtractionContext context) {
if (!context.isValid()) {
if (!context.isValid() || !ParameterizedTestSupport.isAvailable()) {
return Optional.empty();
}

ParameterExtractionHandler foundHandler = null;
Class<? extends Annotation> foundAnnotation = null;

for (Annotation annotation : context.getAnnotations()) {
// Only process JUnit params annotations
if (!ParameterizedTestSupport.isJunitParamsAnnotation(annotation)) {
continue;
}

Class<? extends Annotation> annotationType = annotation.annotationType();
ParameterExtractionHandler handler = handlerMap.get(annotationType);

Expand All @@ -92,14 +89,24 @@ public Optional<ParameterExtractionHandler> findHandler(ParameterExtractionConte
}

private void registerDefaultHandlers() {
handlerMap.put(ValueSource.class, new ValueSourceHandler());
handlerMap.put(EnumSource.class, new EnumSourceHandler());
handlerMap.put(CsvSource.class, new CsvSourceHandler());
handlerMap.put(CsvFileSource.class, new CsvFileSourceHandler());
handlerMap.put(MethodSource.class, new MethodSourceHandler());
handlerMap.put(ArgumentsSource.class, new ArgumentsSourceHandler());
handlerMap.put(NullAndEmptySource.class, new NullAndEmptySourceHandler());
handlerMap.put(NullSource.class, new NullSourceHandler());
handlerMap.put(EmptySource.class, new EmptySourceHandler());
// Only register handlers if JUnit params is available
if (!ParameterizedTestSupport.isAvailable()) {
return;
}

registerHandler("ValueSource", new ValueSourceHandler());
registerHandler("EnumSource", new EnumSourceHandler());
registerHandler("CsvSource", new CsvSourceHandler());
registerHandler("CsvFileSource", new CsvFileSourceHandler());
registerHandler("MethodSource", new MethodSourceHandler());
registerHandler("ArgumentsSource", new ArgumentsSourceHandler());
registerHandler("NullAndEmptySource", new NullAndEmptySourceHandler());
registerHandler("NullSource", new NullSourceHandler());
registerHandler("EmptySource", new EmptySourceHandler());
}

private void registerHandler(String annotationName, ParameterExtractionHandler handler) {
ParameterizedTestSupport.loadAnnotationClass(annotationName)
.ifPresent(annotationClass -> handlerMap.put(annotationClass, handler));
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package io.testomat.junit.extractor.strategy.handlers;

import io.testomat.junit.extractor.strategy.ParameterExtractionContext;
import io.testomat.junit.util.ParameterizedTestSupport;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import org.junit.jupiter.params.provider.EnumSource;

/**
* Parameter extraction handler for @EnumSource annotated parameterized tests.
Expand All @@ -24,14 +25,31 @@ protected Object parseDisplayNameValue(String valueStr, ParameterExtractionConte

@Override
protected Object extractFromAnnotation(ParameterExtractionContext context) {
EnumSource enumSource = context.getAnnotation(EnumSource.class);
if (enumSource == null) {
if (!ParameterizedTestSupport.isAvailable()) {
return null;
}

return ParameterizedTestSupport.loadAnnotationClass("EnumSource")
.map(enumSourceClass -> {
Annotation enumSource = context.getAnnotation(enumSourceClass);
if (enumSource == null) {
return null;
}
return extractValueFromEnumSource(enumSource, context);
})
.orElse(null);
}

private Object extractValueFromEnumSource(Annotation enumSource,
ParameterExtractionContext context) {
try {
Class<? extends Enum<?>> enumClass = enumSource.value();
Class<?> annotationClass = enumSource.annotationType();

if (enumClass.getName().equals("org.junit.jupiter.params.provider.NullEnum")) {
java.lang.reflect.Method valueMethod = annotationClass.getMethod("value");
Class<? extends Enum<?>> enumClass =
(Class<? extends Enum<?>>) valueMethod.invoke(enumSource);

if (isNullEnum(enumClass)) {
enumClass = inferEnumClassFromMethod(context);
}

Expand All @@ -44,16 +62,11 @@ protected Object extractFromAnnotation(ParameterExtractionContext context) {
return null;
}

String[] names = enumSource.names();
java.lang.reflect.Method namesMethod = annotationClass.getMethod("names");
String[] names = (String[]) namesMethod.invoke(enumSource);

if (names.length > 0) {
for (String name : names) {
try {
return Enum.valueOf((Class) enumClass, name);
} catch (IllegalArgumentException e) {
logger.warn("Could not find enum constant {}", name);
}
}
return null;
return findFirstValidEnumConstant(enumClass, names);
}

return enumConstants[0];
Expand All @@ -64,6 +77,22 @@ protected Object extractFromAnnotation(ParameterExtractionContext context) {
}
}

private boolean isNullEnum(Class<? extends Enum<?>> enumClass) {
return enumClass.getName().equals("org.junit.jupiter.params.provider.NullEnum");
}

private Object findFirstValidEnumConstant(Class<? extends Enum<?>> enumClass,
String[] names) {
for (String name : names) {
try {
return Enum.valueOf((Class) enumClass, name);
} catch (IllegalArgumentException e) {
logger.warn("Could not find enum constant {}", name);
}
}
return null;
}

@SuppressWarnings("unchecked")
private Class<? extends Enum<?>> inferEnumClassFromMethod(ParameterExtractionContext context) {
Method method = context.getTestMethod();
Expand Down Expand Up @@ -95,26 +124,52 @@ private Object parseEnumValue(String value, ParameterExtractionContext context)
return null;
}

if (!ParameterizedTestSupport.isAvailable()) {
return value;
}

try {
EnumSource enumSource = context.getAnnotation(EnumSource.class);
Class<? extends Enum<?>> enumClass = enumSource.value();
return ParameterizedTestSupport.loadAnnotationClass("EnumSource")
.map(enumSourceClass -> {
Annotation enumSource = context.getAnnotation(enumSourceClass);
if (enumSource == null) {
return value;
}
return parseEnumWithReflection(enumSource, trimmed, context);
})
.orElse(value);
} catch (Exception e) {
logger.debug("Failed to parse enum value: {}", trimmed, e);
return value;
}
}

if (enumClass.getName().equals("org.junit.jupiter.params.provider.NullEnum")) {
private Object parseEnumWithReflection(Annotation enumSource, String trimmed,
ParameterExtractionContext context) {
try {
Method valueMethod = enumSource.annotationType().getMethod("value");
Class<? extends Enum<?>> enumClass =
(Class<? extends Enum<?>>) valueMethod.invoke(enumSource);

if (isNullEnum(enumClass)) {
enumClass = inferEnumClassFromMethod(context);
}

if (enumClass != null) {
String enumName = trimmed;
if (trimmed.contains(".")) {
enumName = trimmed.substring(trimmed.lastIndexOf('.') + 1);
}

String enumName = extractEnumName(trimmed);
return Enum.valueOf((Class) enumClass, enumName);
}
} catch (Exception e) {
logger.debug("Failed to parse enum value: {}", trimmed, e);
logger.debug("Failed to parse enum value with reflection: {}", trimmed, e);
}

return value;
return trimmed;
}

private String extractEnumName(String trimmed) {
if (trimmed.contains(".")) {
return trimmed.substring(trimmed.lastIndexOf('.') + 1);
}
return trimmed;
}
}
Loading