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

org.jnario.runner.ExampleGroupRunner Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2012 BMW Car IT and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package org.jnario.runner;

import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.newArrayListWithExpectedSize;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static org.eclipse.xtext.xbase.lib.Exceptions.sneakyThrow;
import static org.jnario.runner.ExtensionRule.createClassExtensionRule;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.xtext.xbase.lib.Exceptions;
import org.jnario.runner.internal.ExampleGroupRunnerBuilder;
import org.jnario.runner.internal.ExtensionClass;
import org.jnario.runner.internal.RunAfters;
import org.jnario.runner.internal.RunBefores;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.NoTestsRemainException;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.ParentRunner;
import org.junit.runners.Suite;
import org.junit.runners.model.FrameworkField;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.junit.runners.model.TestClass;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;

/**
 * The Jnario spec {@link Runner} features full text descriptions for tests and
 * classes annotated with {@link Named}. It combines the functionality of a
 * {@link BlockJUnit4ClassRunner} with a {@link Suite} to enable nesting specs and facts.
 * Nested specs can be declared using the {@link Contains} annotation.
 * 
 * @author Sebastian Benz - Initial contribution and API
 */
public class ExampleGroupRunner extends ParentRunner {

	private final class IsTestMethod implements Predicate {
		public boolean apply(FrameworkMethod input) {
			return input.getMethod().getDeclaringClass() == getTestClass()
					.getJavaClass();
		}
	}

	private final NameProvider nameProvider;
	private List children;
	private List extensions;
	private Set setups;

	public ExampleGroupRunner(Class testClass) throws InitializationError {
		this(testClass, NameProvider.create(), new HashSet());
	}

	public ExampleGroupRunner(Class testClass, NameProvider nameProvider, Set setups)
			throws InitializationError {
		super(testClass);
		this.nameProvider = nameProvider;
		this.setups = setups;
		setExtensions();
		setChildren();
	}

	private void setChildren() throws InitializationError {
		Iterable allExamples = concat(collectExampleGroups(),
				collectExamples());
		this.children = newArrayList(Iterables.filter(allExamples, notNull()));
	}

	private void setExtensions() {
		TestClass testClass = getTestClass();
		List extensionFields = testClass.getAnnotatedFields(Extension.class);
		extensions = newArrayListWithExpectedSize(extensionFields.size());
		for (FrameworkField frameworkField : extensionFields) {
			extensions.add(new ExtensionClass(frameworkField));
		}
	}

	@Override
	protected String getName() {
		return nameProvider.nameOf(getTestClass().getJavaClass());
	}

	@Override
	protected List getChildren() {
		return children;
	}

	protected NameProvider getNameProvider() {
		return nameProvider;
	}

	protected Iterable collectExamples() {
		List methods = getTestClass().getAnnotatedMethods(Test.class);
		methods = newArrayList(Iterables.filter(methods, isTestMethod()));
		orderMethods(methods);
		return createRunners(getTestClass().getJavaClass(), methods);
	}

	protected Predicate isTestMethod() {
		return new IsTestMethod();
	}

	protected Iterable createRunners(
			final Class testClass, List annotatedMethods) {
		return transform(annotatedMethods,
				new Function() {
					public Runner apply(FrameworkMethod from) {
						try {
							return createExampleRunner(testClass, from);
						} catch (InitializationError e) {
							sneakyThrow(e);
							return null; // not reachable
						} catch (NoTestsRemainException e) {
							Exceptions.sneakyThrow(e);
							return null; // not reachable
						}
					}
				});
	}

	protected void orderMethods(List annotatedMethods) {
		Collections.sort(annotatedMethods, new Comparator() {

			public int compare(FrameworkMethod method1, FrameworkMethod method2) {
				Order o1 = method1.getAnnotation(Order.class);
				Order o2 = method2.getAnnotation(Order.class);
				if (o1 == null && o2 == null) {
					return 0;
				}
				if (o1 != null && o2 == null) {
					return -1;
				}
				if (o1 == null && o2 != null) {
					return 1;
				}
				return o1.value() - o2.value();
			}

		});
	}

	protected ExampleRunner createExampleRunner(Class testClass,
			FrameworkMethod from) throws InitializationError,
			NoTestsRemainException {
		return new ExampleRunner(testClass, extensions, from, nameProvider,
				createTestInstantiator());
	}

	protected SpecCreator createTestInstantiator() throws InitializationError {
		CreateWith annotation = getCreateWithAnnotation();
		try {
			if (annotation == null) {
				return new SimpleSpecCreator();
			} else {
				return annotation.value().newInstance();
			}
		} catch (Exception e) {
			throw new InitializationError(e);
		}
	}

	protected CreateWith getCreateWithAnnotation() {
		Class klass = targetClass();
		CreateWith annotation = null;
		while (annotation == null && klass != null) {
			annotation = klass.getAnnotation(CreateWith.class);
			klass = klass.getSuperclass();
		}
		return annotation;
	}

	protected Iterable collectExampleGroups() {
		return transform(allDeclaredClasses(),
				new Function, Runner>() {

					public Runner apply(Class declaredClass) {
						try {
							return createExampleGroupRunner(declaredClass);
						} catch (InitializationError e) {
							Exceptions.sneakyThrow(e);
							return null; //not reachable
						}
					}

				});
	}

	protected Runner createExampleGroupRunner(Class declaredClass)
			throws InitializationError {
		return new ExampleGroupRunnerBuilder(declaredClass, nameProvider, setups)
				.build();
	}

	protected List> allDeclaredClasses() {
		List> declaredClasses = asList(targetClass()
				.getDeclaredClasses());
		Iterable> containedClasses = allContainedClasses();
		return newArrayList(concat(declaredClasses, containedClasses));
	}

	protected Iterable> allContainedClasses() {
		Iterable> containedClasses = emptyList();
		Contains contains = targetClass().getAnnotation(Contains.class);
		if (contains != null) {
			containedClasses = asList(contains.value());
		}
		return containedClasses;
	}

	protected Class targetClass() {
		return getTestClass().getJavaClass();
	}

	@Override
	protected Description describeChild(Runner child) {
		return child.getDescription();
	}

	@Override
	protected void runChild(Runner child, RunNotifier notifier) {
		child.run(notifier);
	}
	
	@Override
	protected List classRules() {
		List rules = super.classRules();
		rules.add(createClassExtensionRule(staticExtensions(), null, setups));
		return rules;
	}
	
	@Override
	protected Statement withBeforeClasses(Statement statement) {
		List befores= getTestClass().getAnnotatedMethods(BeforeClass.class);
		List filteredBefores = filterAlreadyScheduled(befores);
		return filteredBefores.isEmpty() ? statement :
			new RunBefores(statement, filteredBefores, null);
	}
	
	@Override
	protected Statement withAfterClasses(Statement statement) {
		List befores= getTestClass().getAnnotatedMethods(AfterClass.class);
		List filteredAfters = filterAlreadyScheduled(befores);
		return filteredAfters.isEmpty() ? statement :
			new RunAfters(statement, filteredAfters, null);
	}

	public List filterAlreadyScheduled(
			List befores) {
		List filteredAfters = new ArrayList(befores.size());
		for (FrameworkMethod frameworkMethod : befores) {
			if(!setups.contains(frameworkMethod.getMethod())){
				filteredAfters.add(frameworkMethod);
				setups.add(frameworkMethod.getMethod());
			}
		}
		return filteredAfters;
	}

	private Iterable staticExtensions() {
		Iterable staticExtensions =  Iterables.filter(extensions, new Predicate() {
			public boolean apply(ExtensionClass extension){
				return extension.isStatic();
			}
		});
		return staticExtensions;
	}
	
	protected List getExtensions() {
		return extensions;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy