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

org.junit.extensions.cpsuite.ClasspathSuite Maven / Gradle / Ivy

/*
 * @author Johannes Link ([email protected])
 * 
 * Published under Apache License, Version 2.0 (http://apache.org/licenses/LICENSE-2.0)
 */
package org.junit.extensions.cpsuite;

import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;

import org.junit.runner.notification.*;
import org.junit.runners.Suite;
import org.junit.runners.model.*;

public class ClasspathSuite extends Suite {

	private static final boolean DEFAULT_INCLUDE_JARS = false;
	private static final SuiteType[] DEFAULT_SUITE_TYPES = new SuiteType[] { SuiteType.TEST_CLASSES };
	private static final Class[] DEFAULT_BASE_TYPES = new Class[] { Object.class };
	private static final Class[] DEFAULT_EXCLUDED_BASES_TYPES = new Class[0];
	private static final String[] DEFAULT_CLASSNAME_FILTERS = new String[0];
	private static final String DEFAULT_CLASSPATH_PROPERTY = "java.class.path";

	private final Class suiteClass;

	/**
	 * The ClassnameFilters annotation specifies a set of regex
	 * expressions for all test classes (ie. their qualified names) to include
	 * in the test run. When the annotation is missing, all test classes in all
	 * packages will be run.
	 */
	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.TYPE)
	public @interface ClassnameFilters {
		public String[] value();
	}

	/**
	 * The IncludeJars annotation specifies if Jars should be
	 * searched in or not. If the annotation is missing Jars are not being
	 * searched.
	 */
	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.TYPE)
	public @interface IncludeJars {
		public boolean value();
	}

	/**
	 * The SuiteTypes annotation specifies which types of tests
	 * will be included in the test run. You can choose one or more from
	 * TEST_CLASSES, RUN_WITH_CLASSES, JUNIT38_TEST_CLASSES. If none is
	 * specified only JUnit4-style TEST_CLASSES will be run.
	 */
	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.TYPE)
	public @interface SuiteTypes {
		public SuiteType[] value();
	}

	/**
	 * The BaseTypeFilter annotation filters all test classes to be
	 * run by one or several given base types, i.e. only those classes will be
	 * run which extend one of the base types. Default is
	 * Object.class.
	 */
	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.TYPE)
	public @interface BaseTypeFilter {
		public Class[] value();
	}

	/**
	 * The ExcludeBaseTypeFilter annotation filters all test
	 * classes to be run by one or several given base types, i.e. only those
	 * classes will be run which do not extend any of the base types.
	 * Default is Object.class.
	 */
	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.TYPE)
	public @interface ExcludeBaseTypeFilter {
		public Class[] value();
	}

	/**
	 * The ClasspathProperty specifies the System property name
	 * used to retrieve the java classpath which is searched for Test classes
	 * and suites. Default is "java.class.path".
	 */
	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.TYPE)
	public @interface ClasspathProperty {
		String value();
	}

	/**
	 * The BeforeSuite marks a method that will be run before the
	 * suite is run.
	 */
	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.METHOD)
	public @interface BeforeSuite {
	}

	/**
	 * Used by JUnit
	 */
	public ClasspathSuite(Class suiteClass, RunnerBuilder builder) throws InitializationError {
		this(suiteClass, builder, new ClasspathFinderFactory());
	}

	/**
	 * For testing purposes only
	 */
	public ClasspathSuite(Class suiteClass, RunnerBuilder builder, ClassesFinderFactory factory) throws InitializationError {
		super(builder, suiteClass, getSortedTestclasses(createFinder(suiteClass, factory)));
		this.suiteClass = suiteClass;
	}

	private static ClassesFinder createFinder(Class suiteClass, ClassesFinderFactory finderFactory) {
		return finderFactory.create(getSearchInJars(suiteClass), getClassnameFilters(suiteClass), getSuiteTypes(suiteClass),
				getBaseTypes(suiteClass), getExcludedBaseTypes(suiteClass), getClasspathProperty(suiteClass));
	}

	private static Class[] getSortedTestclasses(ClassesFinder finder) {
		List> testclasses = finder.find();
		Collections.sort(testclasses, getClassComparator());
		return testclasses.toArray(new Class[testclasses.size()]);
	}

	private static Comparator> getClassComparator() {
		return new Comparator>() {
			public int compare(Class o1, Class o2) {
				return o1.getName().compareTo(o2.getName());
			}
		};
	}

	private static String[] getClassnameFilters(Class suiteClass) {
		ClassnameFilters filtersAnnotation = suiteClass.getAnnotation(ClassnameFilters.class);
		if (filtersAnnotation == null) {
			return DEFAULT_CLASSNAME_FILTERS;
		}
		return filtersAnnotation.value();
	}

	private static boolean getSearchInJars(Class suiteClass) {
		IncludeJars includeJarsAnnotation = suiteClass.getAnnotation(IncludeJars.class);
		if (includeJarsAnnotation == null) {
			return DEFAULT_INCLUDE_JARS;
		}
		return includeJarsAnnotation.value();
	}

	private static SuiteType[] getSuiteTypes(Class suiteClass) {
		SuiteTypes suiteTypesAnnotation = suiteClass.getAnnotation(SuiteTypes.class);
		if (suiteTypesAnnotation == null) {
			return DEFAULT_SUITE_TYPES;
		}
		return suiteTypesAnnotation.value();
	}

	private static Class[] getBaseTypes(Class suiteClass) {
		BaseTypeFilter baseTypeAnnotation = suiteClass.getAnnotation(BaseTypeFilter.class);
		if (baseTypeAnnotation == null) {
			return DEFAULT_BASE_TYPES;
		}
		return baseTypeAnnotation.value();
	}

	private static Class[] getExcludedBaseTypes(Class suiteClass) {
		ExcludeBaseTypeFilter excludeBaseTypeAnnotation = suiteClass.getAnnotation(ExcludeBaseTypeFilter.class);
		if (excludeBaseTypeAnnotation == null) {
			return DEFAULT_EXCLUDED_BASES_TYPES;
		}
		return excludeBaseTypeAnnotation.value();
	}

	private static String getClasspathProperty(Class suiteClass) {
		ClasspathProperty cpPropertyAnnotation = suiteClass.getAnnotation(ClasspathProperty.class);
		if (cpPropertyAnnotation == null) {
			return DEFAULT_CLASSPATH_PROPERTY;
		}
		return cpPropertyAnnotation.value();
	}

	@Override
	public void run(RunNotifier notifier) {
		try {
			runBeforeMethods();
		} catch (Exception e) {
			notifier.fireTestFailure(new Failure(getDescription(), e));
			return;
		}
		super.run(notifier);
	}

	private void runBeforeMethods() throws Exception {
		for (Method each : suiteClass.getMethods()) {
			if (each.isAnnotationPresent(BeforeSuite.class)) {
				if (isPublicStaticVoid(each)) {
					each.invoke(null, new Object[0]);
				}
			}
		}
	}

	private boolean isPublicStaticVoid(Method method) {
		return method.getReturnType() == void.class && method.getParameterTypes().length == 0
				&& (method.getModifiers() & Modifier.STATIC) != 0;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy