All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.slickqa.jupiter.parameterized.SlickParameterizedTestExtension Maven / Gradle / Ivy

package com.slickqa.jupiter.parameterized;

import com.slickqa.jupiter.annotations.ParameterizedTest;
import org.junit.jupiter.api.extension.*;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.junit.jupiter.params.support.AnnotationConsumerInitializer;
import org.junit.platform.commons.JUnitException;
import org.junit.platform.commons.util.ExceptionUtils;
import org.junit.platform.commons.util.Preconditions;
import org.junit.platform.commons.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Stream;

import static org.junit.platform.commons.util.AnnotationUtils.*;

public class SlickParameterizedTestExtension implements TestTemplateInvocationContextProvider {

    private static final String METHOD_CONTEXT_KEY = "context";

    @Override
    public boolean supportsTestTemplate(ExtensionContext context) {
        if (!context.getTestMethod().isPresent()) {
            return false;
        }

        Method testMethod = context.getTestMethod().get();
        if (!isAnnotated(testMethod, ParameterizedTest.class)) {
            return false;
        }

        ParameterizedTestMethodContext methodContext = new ParameterizedTestMethodContext(testMethod);

        Preconditions.condition(methodContext.hasPotentiallyValidSignature(),
                () -> String.format(
                        "@ParameterizedTest method [%s] declares formal parameters in an invalid order: "
                                + "argument aggregators must be declared after any indexed arguments "
                                + "and before any arguments resolved by another ParameterResolver.",
                        testMethod.toGenericString()));

        getStore(context).put(METHOD_CONTEXT_KEY, methodContext);

        return true;
    }

    @Override
    public Stream provideTestTemplateInvocationContexts(
            ExtensionContext extensionContext) {

        Method templateMethod = extensionContext.getRequiredTestMethod();
        String displayName = extensionContext.getDisplayName();
        ParameterizedTestMethodContext methodContext = getStore(extensionContext)//
                .get(METHOD_CONTEXT_KEY, ParameterizedTestMethodContext.class);
        ParameterizedTestNameFormatter formatter = createNameFormatter(templateMethod, displayName);
        AtomicLong invocationCount = new AtomicLong(0);
        ArgumentsChecksumStore checksums = new ArgumentsChecksumStore();
        extensionContext.getStore(ExtensionContext.Namespace.create(ArgumentsChecksumStore.class, templateMethod)).put("checksums", checksums);

        if(System.getenv("SLICK_DATA_DRIVEN") != null) {
            return Arrays.asList((TestTemplateInvocationContext)new SlickTemplateInvocationContext(formatter, methodContext)).stream();
        }

        // @formatter:off
        return findRepeatableAnnotations(templateMethod, ArgumentsSource.class)
                .stream()
                .map(ArgumentsSource::value)
                .map(this::instantiateArgumentsProvider)
                .map(provider -> AnnotationConsumerInitializer.initialize(templateMethod, provider))
                .flatMap(provider -> arguments(provider, extensionContext))
                .map(Arguments::get)
                .map(arguments -> checksumArguments(arguments, invocationCount.get(), checksums))
                .map(arguments -> consumedArguments(arguments, methodContext))
                .map(arguments -> createInvocationContext(formatter, methodContext, arguments))
                .peek(invocationContext -> invocationCount.incrementAndGet())
                .onClose(() ->
                        Preconditions.condition(invocationCount.get() > 0,
                                "Configuration error: You must configure at least one set of arguments for this @ParameterizedTest"));
        // @formatter:on
    }

    @SuppressWarnings("ConstantConditions")
    private ArgumentsProvider instantiateArgumentsProvider(Class clazz) {
        try {
            return ReflectionUtils.newInstance(clazz);
        }
        catch (Exception ex) {
            if (ex instanceof NoSuchMethodException) {
                String message = String.format("Failed to find a no-argument constructor for ArgumentsProvider [%s]. "
                                + "Please ensure that a no-argument constructor exists and "
                                + "that the class is either a top-level class or a static nested class",
                        clazz.getName());
                throw new JUnitException(message, ex);
            }
            throw ex;
        }
    }

    private ExtensionContext.Store getStore(ExtensionContext context) {
        return context.getStore(ExtensionContext.Namespace.create(SlickParameterizedTestExtension.class, context.getRequiredTestMethod()));
    }

    private TestTemplateInvocationContext createInvocationContext(ParameterizedTestNameFormatter formatter,
                                                                  ParameterizedTestMethodContext methodContext, Object[] arguments) {
        return new ParameterizedTestInvocationContext(formatter, methodContext, arguments);
    }

    private ParameterizedTestNameFormatter createNameFormatter(Method templateMethod, String displayName) {
        ParameterizedTest parameterizedTest = findAnnotation(templateMethod, ParameterizedTest.class).get();
        String pattern = Preconditions.notBlank(parameterizedTest.name().trim(),
                () -> String.format(
                        "Configuration error: @ParameterizedTest on method [%s] must be declared with a non-empty name.",
                        templateMethod));
        return new ParameterizedTestNameFormatter(pattern, displayName);
    }

    protected static Stream arguments(ArgumentsProvider provider, ExtensionContext context) {
        try {
            return provider.provideArguments(context);
        }
        catch (Exception e) {
            throw ExceptionUtils.throwAsUncheckedException(e);
        }
    }

    private Object[] checksumArguments(Object[] arguments, long index, ArgumentsChecksumStore store) {
        // compute checksum here
        store.putChecksum(index + 1, Checksum.generateFor(arguments));
        return arguments;
    }

    private Object[] consumedArguments(Object[] arguments, ParameterizedTestMethodContext methodContext) {
        int parameterCount = methodContext.getParameterCount();
        return methodContext.hasAggregator() ? arguments
                : (arguments.length > parameterCount ? Arrays.copyOf(arguments, parameterCount) : arguments);
    }

}
/*
    @Override
    public boolean supportsTestTemplate(ExtensionContext context) {
        if (!context.getTestMethod().isPresent()) {
            return false;
        }

        Method testMethod = context.getTestMethod().get();
        try {
            String message = MessageFormat.format("supportsTestTemplate(method: {0}) called\n", testMethod.getName());
            Files.write(Paths.get("tester.log"), message.getBytes(), StandardOpenOption.APPEND, StandardOpenOption.CREATE);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    @Override
    public Stream provideTestTemplateInvocationContexts(ExtensionContext context) {
        return null;
    }
}

 */




© 2015 - 2025 Weber Informatics LLC | Privacy Policy