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

org.unitils.UnitilsParameterized Maven / Gradle / Ivy

package org.unitils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.internal.runners.InitializationError;
import org.junit.internal.runners.MethodValidator;
import org.junit.runner.Runner;
import org.junit.runners.Parameterized.Parameters;
import org.junit.runners.Suite;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.TestClass;


/**
 * Parameterized runner.
 * 
 * @author Jeroen Horemans
 * @author Thomas De Rycke
 * @author Willemijn Wouters
 * 
 * @since 3.4
 * 
 */
public class UnitilsParameterized extends Suite {
    private Class clazz;
    private static final Log LOGGER = LogFactory.getLog(UnitilsParameterized.class);
    private static final String METHOD = "Method ";
    /**
     * 
     * TestClassRunnerForParameters.
     * 
     * @author wiw
     * 
     * @since 
     *
     */
    protected class TestClassRunnerForParameters extends UnitilsJUnit4TestClassRunner {

        private final int fParameterSetNumber;

        private final List fParameterList;

        private org.junit.internal.runners.TestClass testClassInternalRunners;
        /**
         * @param javaClass
         * @param parametersList
         * @param i
         * @throws Exception 
         */
        public TestClassRunnerForParameters(Class javaClass, List parametersList, int i) throws Exception {
            super(javaClass);
            this.fParameterList = parametersList;
            this.fParameterSetNumber = i;
            this.testClassInternalRunners = new org.junit.internal.runners.TestClass(javaClass);
        }
        

        /**
         * @see org.junit.internal.runners.JUnit4ClassRunner#createTest()
         */
        @Override
        protected Object createTest() throws Exception {
            return getfTestClass().getOnlyConstructor().newInstance(computeParams());
        }

        /**
         * @return
         */
        private TestClass getfTestClass() {
            return  new TestClass(clazz);
        }

        /**
         * @return
         * @throws Exception 
         */
        protected Object[] computeParams() throws Exception {
            try {
                return fParameterList.get(fParameterSetNumber);
            } catch (ClassCastException e) {
                throw new Exception(String.format("%s.%s() must return a Collection of arrays.", getTestClass().getName(), getParametersMethod(getfTestClass()).getName()));
            }
        }
        /**
         * @see org.junit.internal.runners.JUnit4ClassRunner#getName()
         */
        @Override
        protected String getName() {
            StringBuffer name = new StringBuffer();
            try {
                Object[] data = fParameterList.get(fParameterSetNumber);
                for (Object object : data) {
                    if (object != null) {
                        name.append(object.toString());
                        name.append(",");
                    } else {
                        name.append("null,");
                    }

                }
            } catch (IndexOutOfBoundsException e) {
                LOGGER.error(e.getMessage(), e);
            }
            name = new StringBuffer(name.substring(0, name.length() - 1));

            return String.format("dataset [%s]", name.toString());
        }

        /**
         * @see org.junit.internal.runners.JUnit4ClassRunner#testName(java.lang.reflect.Method)
         */
        @Override
        protected String testName(Method method) {
            return String.format("%s[%s]", method.getName(), fParameterSetNumber);
        }

        /**
         * @see org.junit.internal.runners.JUnit4ClassRunner#validate()
         */
        @Override
        protected void validate() throws InitializationError {
            testClassInternalRunners = new org.junit.internal.runners.TestClass(clazz);
            UnitilsMethodValidator validator = new UnitilsMethodValidator(testClassInternalRunners);
            List errors = validator.validateMethodsForParameterizedRunner();
            if (!errors.isEmpty()) {
                throw new InitializationError(errors);
            }
        }
        
    }
    private final List runners= new ArrayList();

    

    /**
     * Only called reflectively. Do not use programmatically.
     * @param klass 
     * @throws Throwable 
     */
    public UnitilsParameterized(Class klass) throws Throwable {
        super(klass, Collections.emptyList());
        this.clazz = klass;
        List parametersList = getParametersList(getTestClass());
        for (int i= 0; i < parametersList.size(); i++) {
            runners.add(new TestClassRunnerForParameters(getTestClass().getJavaClass(), parametersList, i));

        }
    }

    /**
     * @param testClass
     * @return {@link List}
     * @throws Throwable 
     * @throws Exception 
     */
    @SuppressWarnings("unchecked")
    private List getParametersList(TestClass testClass) throws Exception, Throwable {
        return (List) getParametersMethod(testClass).invokeExplosively(null);
    }

    /**
     * @param testClass
     * @return
     */
    protected FrameworkMethod getParametersMethod(TestClass testClass) throws Exception {
        List methods = testClass.getAnnotatedMethods(Parameters.class);
        
        for (FrameworkMethod each : methods) {
            int modifiers = each.getMethod().getModifiers();
            if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)) {
                return each;
            }

        }

        throw new Exception("No public static parameters method on class " + testClass.getName());
    }
    /**
     * @see org.junit.runners.Suite#getChildren()
     */
    @Override
    protected List getChildren() {
        return Collections.unmodifiableList(runners);
    }
    /**
     * 
     * UnitilsMethodValidator.
     * 
     * @author wiw
     * 
     * @since 
     *
     */
    protected static class UnitilsMethodValidator extends MethodValidator {

        private org.junit.internal.runners.TestClass testclass;
        private List errors = new ArrayList();
        /**
         * @param testClass
         */
        public UnitilsMethodValidator(org.junit.internal.runners.TestClass testClass) {
            super(testClass);
            this.testclass = testClass;
        }
        public List validateMethodsForParameterizedRunner() {
            validateArgConstructor();
            validateStaticMethods();
            validateInstanceMethods();

            return errors;
        }   



        //private methods
        protected void validateTestMethods(Class annotation, boolean isStatic) {
            List methods= testclass.getAnnotatedMethods(annotation);

            for (Method each : methods) {
                if (Modifier.isStatic(each.getModifiers()) != isStatic) {
                    String state= isStatic ? "should" : "should not";
                    errors.add(new Exception(METHOD + each.getName() + "() "
                        + state + " be static"));
                }
                if (!Modifier.isPublic(each.getDeclaringClass().getModifiers())) {
                    errors.add(new Exception("Class " + each.getDeclaringClass().getName() + " should be public"));
                }
                if (!Modifier.isPublic(each.getModifiers())) {
                    errors.add(new Exception(METHOD + each.getName() + " should be public"));
                }
                if (each.getReturnType() != Void.TYPE) {
                    errors.add(new Exception(METHOD + each.getName() + " should be void"));
                }
                if (each.getParameterTypes().length != 0) {
                    errors.add(new Exception(METHOD + each.getName()  + " should have no parameters"));
                }
            }
        }

        /**
         * @see org.junit.internal.runners.MethodValidator#validateInstanceMethods()
         */
        @Override
        public void validateInstanceMethods() {
            validateTestMethods(After.class, false);
            validateTestMethods(Before.class, false);
            validateTestMethods(Test.class, false);

            List methods= testclass.getAnnotatedMethods(Test.class);
            if (methods.size() == 0) {
                errors.add(new Exception("No runnable methods"));
            }
        }

        /**
         * @see org.junit.internal.runners.MethodValidator#validateStaticMethods()
         */
        @Override
        public void validateStaticMethods() {
            validateTestMethods(BeforeClass.class, true);
            validateTestMethods(AfterClass.class, true);
        }
        public void validateArgConstructor() {
            org.junit.runners.model.TestClass clazz = new org.junit.runners.model.TestClass(testclass.getJavaClass());
            Constructor onlyConstructor = clazz.getOnlyConstructor();
            
            if (onlyConstructor.getParameterTypes().length == 0) {
                errors.add(new Exception("Test class shouldn't have a public zero-argument constructor"));
            }

        }


        /**
         * @return the errors
         */
        protected List getErrors() {
            return errors;
        }
        
        
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy