Skip to content

Commit

Permalink
first hacky idea, not sure if this should be within core or a custom …
Browse files Browse the repository at this point in the history
…extension, done by the user ... (#101)
  • Loading branch information
aaschmid committed Nov 4, 2017
1 parent 6174fe0 commit 13a253d
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
* </tr>
* </table>
*/
abstract class AbstractArgumentPlaceholder extends BasePlaceholder {
public abstract class AbstractArgumentPlaceholder extends BasePlaceholder {

/**
* {@link String} representation of {@code null}
Expand All @@ -47,7 +47,7 @@ abstract class AbstractArgumentPlaceholder extends BasePlaceholder {
*/
protected static final String STRING_NON_PRINTABLE = "<np>";

AbstractArgumentPlaceholder(String placeholderRegex) {
protected AbstractArgumentPlaceholder(String placeholderRegex) {
super(placeholderRegex);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.tngtech.test.junit.dataprovider.custom.argformat;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;

import com.tngtech.junit.dataprovider.placeholder.AbstractArgumentPlaceholder;
import com.tngtech.junit.dataprovider.placeholder.NamedArgumentPlaceholder;
import com.tngtech.junit.dataprovider.placeholder.ReplacementData;

class AnnotationArgumentPlaceholder extends AbstractArgumentPlaceholder {

private static final Logger logger = Logger.getLogger(NamedArgumentPlaceholder.class.getName());

public AnnotationArgumentPlaceholder() {
super("%aa\\[(-?[0-9]+|-?[0-9]+\\.\\.-?[0-9]+)\\]");
}

@Override
protected String getReplacementFor(String placeholder, ReplacementData data) {
String subscript = placeholder.substring(4, placeholder.length() - 1);

int from = Integer.MAX_VALUE;
int to = Integer.MIN_VALUE;
if (subscript.contains("..")) {
String[] split = subscript.split("\\.\\.");

from = Integer.parseInt(split[0]);
to = Integer.parseInt(split[1]);
} else {
from = Integer.parseInt(subscript);
to = from;
}

data.getTestMethod().getAnnotatedParameterTypes();

List<Object> arguments = data.getArguments();
from = (from >= 0) ? from : arguments.size() + from;
to = (to >= 0) ? to + 1 : arguments.size() + to + 1;
return formatAll(getSubArrayOfMethodParameters(data.getTestMethod(), from, to),
arguments.subList(from, to));
}

/**
* Formats the given parameters and arguments to a comma-separated list of {@code $parameterName=$argumentName}.
* Arguments {@link String} representation are therefore treated specially.
*
* @param parameters used to for formatting
* @param arguments to be formatted
* @return the formatted {@link String} of the given {@link Parameter}{@code []} and {@link List}{@code <Object>}
*/
protected String formatAll(Parameter[] parameters, List<Object> arguments) {
StringBuilder stringBuilder = new StringBuilder();
for (int idx = 0; idx < arguments.size(); idx++) {
Parameter parameter = parameters[idx];
Object argument = arguments.get(idx);

Format annotation = parameter.getAnnotation(Format.class);
if (annotation != null) {
try {
stringBuilder.append(annotation.value().newInstance().format(argument));

} catch (InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
stringBuilder.append(format(argument));
}

if (idx < arguments.size() - 1) {
stringBuilder.append(", ");
}
}
return stringBuilder.toString();
}

private Parameter[] getSubArrayOfMethodParameters(Method testMethod, int fromIndex, int toIndex) {
Parameter[] parameters = testMethod.getParameters();
if (parameters.length > 0 && !parameters[0].isNamePresent()) {
logger.warning(String.format("Parameter names on method '%s' are not available"
+ ". To store formal parameter names, compile the source file with the '-parameters' option"
+ ". See also https://docs.oracle.com/javase/tutorial/reflect/member/methodparameterreflection.html",
testMethod));
}
return Arrays.copyOfRange(parameters, fromIndex, toIndex);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.tngtech.test.junit.dataprovider.custom.argformat;

import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith;

import com.tngtech.junit.dataprovider.DataProvider;
import com.tngtech.junit.dataprovider.UseDataProvider;

@ExtendWith(AnnotationArgumentPlaceholderDataProviderExtension.class)
class AnnotationArgumentPlaceholderAcceptanceTest {

@DataProvider(format = "[%i: %aa[0..-1]]")
static Object[][] dataProvider() {
// @formatter:off
return new Object[][] {
{ new WrappedClass(AnnotationArgumentPlaceholderAcceptanceTest.class) },
};
// @formatter:on
}

@TestTemplate
@UseDataProvider
void test(@Format(UnwrapFormatter.class) WrappedClass clazz) {
// TODO
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.tngtech.test.junit.dataprovider.custom.argformat;

import static java.util.Arrays.asList;

import java.util.List;

import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.platform.commons.support.ReflectionSupport;

import com.tngtech.junit.dataprovider.DataProvider;
import com.tngtech.junit.dataprovider.DisplayNameContext;
import com.tngtech.junit.dataprovider.UseDataProvider;
import com.tngtech.junit.dataprovider.UseDataProviderInvocationContextProvider;
import com.tngtech.junit.dataprovider.convert.ConverterContext;
import com.tngtech.junit.dataprovider.placeholder.BasePlaceholder;
import com.tngtech.junit.dataprovider.resolver.DataProviderResolverContext;

class AnnotationArgumentPlaceholderDataProviderExtension
extends UseDataProviderInvocationContextProvider<UseDataProvider, DataProvider> {

AnnotationArgumentPlaceholderDataProviderExtension() {
super(UseDataProvider.class, DataProvider.class);
}

@Override
protected DataProviderResolverContext getDataProviderResolverContext(ExtensionContext extensionContext,
UseDataProvider testAnnotation) {
return new DataProviderResolverContext(extensionContext.getRequiredTestMethod(),
asList(testAnnotation.resolver()), testAnnotation.resolveStrategy(), asList(testAnnotation.location()),
DataProvider.class, testAnnotation.value());
}

@Override
protected ConverterContext getConverterContext(DataProvider dataProvider) {
return new ConverterContext(ReflectionSupport.newInstance(dataProvider.objectArrayConverter()),
ReflectionSupport.newInstance(dataProvider.singleArgConverter()),
ReflectionSupport.newInstance(dataProvider.stringConverter()), dataProvider.splitBy(),
dataProvider.convertNulls(), dataProvider.trimValues(), dataProvider.ignoreEnumCase());
}

@Override
protected DisplayNameContext getDisplayNameContext(DataProvider dataProvider) {
@SuppressWarnings("unchecked")
List<BasePlaceholder> defaultPlaceholders = (List<BasePlaceholder>) getDefaultPlaceholders();
defaultPlaceholders.add(0, new AnnotationArgumentPlaceholder());
return new DisplayNameContext(dataProvider.format(), defaultPlaceholders);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.tngtech.test.junit.dataprovider.custom.argformat;

public interface ArgumentFormatter<T> {

String format(T argument);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.tngtech.test.junit.dataprovider.custom.argformat;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Format {

Class<? extends ArgumentFormatter> value();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.tngtech.test.junit.dataprovider.custom.argformat;

public class UnwrapFormatter implements ArgumentFormatter<WrappedClass> {

@Override
public String format(WrappedClass argument) {
return argument.getWrappedClazz().getSimpleName();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.tngtech.test.junit.dataprovider.custom.argformat;

class WrappedClass {
private final Class<?> clazz;

WrappedClass(Class<?> clazz) {
this.clazz = clazz;
}

public Class<?> getWrappedClazz() {
return clazz;
}

@Override
public String toString() {
return "WrappedClass [clazz=" + clazz + "]";
}
}

0 comments on commit 13a253d

Please sign in to comment.