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

com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner Maven / Gradle / Ivy

Go to download

Library designed to make JBehave stories & scenarios show up in the JUnit view in IDEs supportting custom test runners

There is a newer version: 2.3.2
Show newest version
package com.github.valfirst.jbehave.junit.monitoring;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.jbehave.core.ConfigurableEmbedder;
import org.jbehave.core.configuration.Configuration;
import org.jbehave.core.embedder.Embedder;
import org.jbehave.core.embedder.EmbedderControls;
import org.jbehave.core.embedder.PerformableTree;
import org.jbehave.core.embedder.PerformableTree.RunContext;
import org.jbehave.core.failures.BatchFailures;
import org.jbehave.core.junit.JUnitStories;
import org.jbehave.core.junit.JUnitStory;
import org.jbehave.core.model.Story;
import org.jbehave.core.reporters.StoryReporterBuilder;
import org.jbehave.core.steps.CandidateSteps;
import org.jbehave.core.steps.InjectableStepsFactory;
import org.jbehave.core.steps.NullStepMonitor;
import org.jbehave.core.steps.StepMonitor;
import org.junit.runner.Description;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;

public class JUnitReportingRunner extends BlockJUnit4ClassRunner {
	private Embedder configuredEmbedder;
	private Configuration configuration;
	private int numberOfTestCases;
	private Description rootDescription;
	private ConfigurableEmbedder configurableEmbedder;

	public JUnitReportingRunner(Class testClass)
			throws InitializationError, ReflectiveOperationException {
		super(testClass);
		configurableEmbedder = testClass.newInstance();
		configuredEmbedder = configurableEmbedder.configuredEmbedder();
		configuration = configuredEmbedder.configuration();

		List storyPaths = getStoryPaths(testClass);

		StepMonitor originalStepMonitor = configuration.stepMonitor();
		configuration.useStepMonitor(new NullStepMonitor());
		List storyDescriptions = buildDescriptionFromStories(storyPaths);
		configuration.useStepMonitor(originalStepMonitor);

		rootDescription = Description.createSuiteDescription(testClass);
		for (Description storyDescription : storyDescriptions) {
			rootDescription.addChild(storyDescription);
		}
	}

	@Override
	public Description getDescription() {
		return rootDescription;
	}

	@Override
	public int testCount() {
		return numberOfTestCases;
	}

	/**
	 * Returns a {@link Statement}: Call {@link #runChild(Object, RunNotifier)}
	 * on each object returned by {@link #getChildren()} (subject to any imposed
	 * filter and sort)
	 */
	@Override
	protected Statement childrenInvoker(final RunNotifier notifier) {
		return new Statement() {
			@Override
			public void evaluate() {
				JUnitScenarioReporter junitReporter = new JUnitScenarioReporter(
				notifier, numberOfTestCases, rootDescription, configuration.keywords());
				// tell the reporter how to handle pending steps
				junitReporter.usePendingStepStrategy(configuration
						.pendingStepStrategy());

				addToStoryReporterFormats(junitReporter);

				try {
					configurableEmbedder.run();
				} catch (Throwable e) {
					throw new RuntimeException(e);
				}
			}
		};
	}

	public static EmbedderControls recommendedControls(Embedder embedder) {
		return embedder.embedderControls()
		// don't throw an exception on generating reports for failing stories
				.doIgnoreFailureInView(true)
				// don't throw an exception when a story failed
				.doIgnoreFailureInStories(true)
				// .doVerboseFailures(true)
				.useThreads(1);
	}

	private List getStoryPaths(Class testClass)
			throws ReflectiveOperationException {
		if (JUnitStories.class.isAssignableFrom(testClass)) {
			return getStoryPathsFromJUnitStories(testClass);
		} else if (JUnitStory.class.isAssignableFrom(testClass)) {
			return Arrays.asList(configuration.storyPathResolver().resolve(testClass));
		} else {
			throw new IllegalArgumentException(
					"Only ConfigurableEmbedder of types JUnitStory and JUnitStories is supported");
		}
	}

	@SuppressWarnings("unchecked")
	private List getStoryPathsFromJUnitStories(
			Class testClass)
			throws ReflectiveOperationException {
		Method method = makeStoryPathsMethodPublic(testClass);
		return ((List) method.invoke(configurableEmbedder, (Object[]) null));
	}

	@SuppressWarnings("unchecked")
    private static Method makeStoryPathsMethodPublic(Class clazz)
			throws NoSuchMethodException {
		try {
			Method method = clazz.getDeclaredMethod("storyPaths", (Class[]) null);
			method.setAccessible(true);
			return method;
		} catch (NoSuchMethodException e) {
			Class superclass = clazz.getSuperclass();
			if (superclass != null && ConfigurableEmbedder.class.isAssignableFrom(superclass)) {
				return makeStoryPathsMethodPublic((Class) superclass);
			}
			throw e;
		}
	}

	private List getCandidateSteps() {
		List candidateSteps;
		InjectableStepsFactory stepsFactory = configurableEmbedder.stepsFactory();
		if (stepsFactory != null) {
			candidateSteps = stepsFactory.createCandidateSteps();
		} else {
			candidateSteps = configuredEmbedder.candidateSteps();
			if (candidateSteps == null || candidateSteps.isEmpty()) {
				candidateSteps = configuredEmbedder.stepsFactory().createCandidateSteps();
			}
		}
		return candidateSteps;
	}

	private void addToStoryReporterFormats(JUnitScenarioReporter junitReporter) {
		StoryReporterBuilder storyReporterBuilder = configuration
				.storyReporterBuilder();
		StoryReporterBuilder.ProvidedFormat junitReportFormat = new StoryReporterBuilder.ProvidedFormat(
				junitReporter);
		storyReporterBuilder.withFormats(junitReportFormat);
	}

	private List buildDescriptionFromStories(List storyPaths) {
		JUnitDescriptionGenerator descriptionGenerator = new JUnitDescriptionGenerator(
				getCandidateSteps(), configuration);
		List storyDescriptions = new ArrayList<>();

		addSuite(storyDescriptions, "BeforeStories");
		storyDescriptions.addAll(descriptionGenerator.createDescriptionFrom(createPerformableTree(storyPaths)));
		addSuite(storyDescriptions, "AfterStories");

		numberOfTestCases += descriptionGenerator.getTestCases();

		return storyDescriptions;
	}

	private PerformableTree createPerformableTree(List storyPaths) {
		BatchFailures failures = new BatchFailures(configuredEmbedder.embedderControls().verboseFailures());
		PerformableTree performableTree = new PerformableTree();
		RunContext context = performableTree.newRunContext(configuration, configuredEmbedder.stepsFactory(),
				configuredEmbedder.embedderMonitor(), configuredEmbedder.metaFilter(), failures);
		performableTree.addStories(context, storiesOf(performableTree, storyPaths));
		return performableTree;
	}

	private List storiesOf(PerformableTree performableTree, List storyPaths) {
		List stories = new ArrayList<>();
		for (String storyPath : storyPaths) {
			stories.add(performableTree.storyOfPath(configuration, storyPath));
		}
		return stories;
	}

	private void addSuite(List storyDescriptions, String name) {
		storyDescriptions.add(Description.createTestDescription(Object.class,
				name));
		numberOfTestCases++;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy