Home | History | Annotate | Download | only in internal
      1 package junitparams.internal;
      2 
      3 import java.lang.annotation.Annotation;
      4 import java.lang.reflect.Method;
      5 import java.util.ArrayList;
      6 import java.util.Arrays;
      7 import java.util.List;
      8 
      9 import org.junit.Ignore;
     10 import org.junit.Test;
     11 import org.junit.runner.Description;
     12 import org.junit.runners.model.FrameworkMethod;
     13 import org.junit.runners.model.TestClass;
     14 
     15 import junitparams.internal.annotation.FrameworkMethodAnnotations;
     16 import junitparams.internal.parameters.ParametersReader;
     17 import junitparams.naming.MacroSubstitutionNamingStrategy;
     18 import junitparams.naming.TestCaseNamingStrategy;
     19 
     20 /**
     21  * A wrapper for a test method
     22  *
     23  * @author Pawel Lipinski
     24  */
     25 public class TestMethod {
     26     private FrameworkMethod frameworkMethod;
     27     private FrameworkMethodAnnotations frameworkMethodAnnotations;
     28     private Class<?> testClass;
     29     private ParametersReader parametersReader;
     30     private Object[] cachedParameters;
     31     private TestCaseNamingStrategy namingStrategy;
     32     private DescribableFrameworkMethod describableFrameworkMethod;
     33 
     34     public TestMethod(FrameworkMethod method, TestClass testClass) {
     35         this.frameworkMethod = method;
     36         this.testClass = testClass.getJavaClass();
     37         frameworkMethodAnnotations = new FrameworkMethodAnnotations(method);
     38         parametersReader = new ParametersReader(testClass(), frameworkMethod);
     39 
     40         namingStrategy = new MacroSubstitutionNamingStrategy(this);
     41     }
     42 
     43     public String name() {
     44         return frameworkMethod.getName();
     45     }
     46 
     47     public static List<FrameworkMethod> listFrom(TestClass testClass) {
     48         List<FrameworkMethod> methods = new ArrayList<FrameworkMethod>();
     49 
     50         for (FrameworkMethod frameworkMethod : testClass.getAnnotatedMethods(Test.class)) {
     51             TestMethod testMethod = new TestMethod(frameworkMethod, testClass);
     52             methods.add(testMethod.describableFrameworkMethod());
     53         }
     54 
     55         return methods;
     56     }
     57 
     58     @Override
     59     public int hashCode() {
     60         return frameworkMethod.hashCode();
     61     }
     62 
     63     @Override
     64     public boolean equals(Object obj) {
     65         return (obj instanceof TestMethod)
     66                 && hasTheSameNameAsFrameworkMethod((TestMethod) obj)
     67                 && hasTheSameParameterTypesAsFrameworkMethod((TestMethod) obj);
     68     }
     69 
     70     private boolean hasTheSameNameAsFrameworkMethod(TestMethod testMethod) {
     71         return frameworkMethod.getName().equals(testMethod.frameworkMethod.getName());
     72     }
     73 
     74     private boolean hasTheSameParameterTypesAsFrameworkMethod(TestMethod testMethod) {
     75         Class<?>[] frameworkMethodParameterTypes = frameworkMethod.getMethod().getParameterTypes();
     76         Class<?>[] testMethodParameterTypes = testMethod.frameworkMethod.getMethod().getParameterTypes();
     77         return Arrays.equals(frameworkMethodParameterTypes, testMethodParameterTypes);
     78     }
     79 
     80     private Class<?> testClass() {
     81         return testClass;
     82     }
     83 
     84     private boolean isIgnored() {
     85         return hasIgnoredAnnotation() || hasNoParameters();
     86     }
     87 
     88     private boolean hasIgnoredAnnotation() {
     89         return frameworkMethodAnnotations.hasAnnotation(Ignore.class);
     90     }
     91 
     92     private boolean hasNoParameters() {
     93        return isParameterised() && parametersSets().length == 0;
     94     }
     95 
     96     private boolean isNotIgnored() {
     97         return !isIgnored();
     98     }
     99 
    100     public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
    101         return frameworkMethodAnnotations.getAnnotation(annotationType);
    102     }
    103 
    104     private Description getDescription(Object[] params, int i) {
    105         Object paramSet = params[i];
    106         String name = namingStrategy.getTestCaseName(i, paramSet);
    107         String uniqueMethodId = Utils.uniqueMethodId(i, paramSet, name());
    108 
    109         return Description.createTestDescription(testClass().getName(), name, uniqueMethodId);
    110     }
    111 
    112     DescribableFrameworkMethod describableFrameworkMethod() {
    113         if (describableFrameworkMethod == null) {
    114             Description baseDescription = Description.createTestDescription(
    115                     testClass, name(), frameworkMethodAnnotations.allAnnotations());
    116             Method method = frameworkMethod.getMethod();
    117             try {
    118                 describableFrameworkMethod =
    119                         createDescribableFrameworkMethod(method, baseDescription);
    120             } catch (IllegalStateException e) {
    121                 // Defer error until running.
    122                 describableFrameworkMethod =
    123                         new DeferredErrorFrameworkMethod(method, baseDescription, e);
    124             }
    125         }
    126 
    127         return describableFrameworkMethod;
    128     }
    129 
    130     private DescribableFrameworkMethod createDescribableFrameworkMethod(Method method, Description baseDescription) {
    131         if (isParameterised()) {
    132             if (isNotIgnored()) {
    133                 Object[] parametersSets = parametersSets();
    134                 List<InstanceFrameworkMethod> methods
    135                         = new ArrayList<InstanceFrameworkMethod>();
    136                 for (int i = 0; i < parametersSets.length; i++) {
    137                     Object parametersSet = parametersSets[i];
    138                     Description description = getDescription(parametersSets, i);
    139                     methods.add(new InstanceFrameworkMethod(
    140                             method, baseDescription.childlessCopy(),
    141                             description, parametersSet));
    142                 }
    143 
    144                 return new ParameterisedFrameworkMethod(method, baseDescription, methods);
    145             }
    146 
    147             warnIfNoParamsGiven();
    148         } else {
    149             verifyMethodCanBeRunByStandardRunner(frameworkMethod);
    150         }
    151 
    152         // The method to use if it was ignored or was parameterized but had no parameters.
    153         return new NonParameterisedFrameworkMethod(method, baseDescription, isIgnored());
    154     }
    155 
    156     private void verifyMethodCanBeRunByStandardRunner(FrameworkMethod method) {
    157         List<Throwable> errors = new ArrayList<Throwable>();
    158         method.validatePublicVoidNoArg(false, errors);
    159         if (!errors.isEmpty()) {
    160             throw new RuntimeException(errors.get(0));
    161         }
    162     }
    163 
    164     public Object[] parametersSets() {
    165         if (cachedParameters == null) {
    166             cachedParameters = parametersReader.read();
    167         }
    168         return cachedParameters;
    169     }
    170 
    171     private void warnIfNoParamsGiven() {
    172         if (isNotIgnored() && isParameterised() && parametersSets().length == 0)
    173             System.err.println("Method " + name() + " gets empty list of parameters, so it's being ignored!");
    174     }
    175 
    176     public FrameworkMethod frameworkMethod() {
    177         return frameworkMethod;
    178     }
    179 
    180     boolean isParameterised() {
    181         return frameworkMethodAnnotations.isParametrised();
    182     }
    183 }
    184