JUnit4StoryRunner.java
package org.jbehave.core.junit;
import java.util.ArrayList;
import java.util.List;
import org.jbehave.core.ConfigurableEmbedder;
import org.jbehave.core.configuration.Configuration;
import org.jbehave.core.embedder.AllStepCandidates;
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.reporters.StoryReporter;
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 JUnit4StoryRunner extends BlockJUnit4ClassRunner {
private final ConfigurableEmbedder configurableEmbedder;
private final Embedder configuredEmbedder;
private final Configuration configuration;
private final Description description;
private int numberOfTestCases;
public JUnit4StoryRunner(Class<? extends ConfigurableEmbedder> testClass)
throws InitializationError, ReflectiveOperationException {
super(testClass);
configurableEmbedder = testClass.getDeclaredConstructor().newInstance();
configuredEmbedder = configurableEmbedder.configuredEmbedder();
configuration = configuredEmbedder.configuration();
List<String> storyPaths = storyPathsFor(configurableEmbedder);
StepMonitor originalStepMonitor = configuration.stepMonitor();
configuration.useStepMonitor(new NullStepMonitor());
List<Description> storyDescriptions = buildDescriptionsFromStories(storyPaths);
configuration.useStepMonitor(originalStepMonitor);
description = Description.createSuiteDescription(testClass);
for (Description storyDescription : storyDescriptions) {
description.addChild(storyDescription);
}
}
private List<String> storyPathsFor(ConfigurableEmbedder configurableEmbedder) {
if (configurableEmbedder instanceof JUnitStories) {
return ((JUnitStories)configurableEmbedder).storyPaths();
}
throw new IllegalArgumentException(
"Only ConfigurableEmbedder of type JUnitStories is supported");
}
@Override
public Description getDescription() {
return description;
}
@Override
public int testCount() {
return numberOfTestCases;
}
/**
* Returns a {@link Statement} execution the {@link ConfigurableEmbedder#run()}
* with a {@link JUnit4StoryReporter}.
*/
@Override
protected Statement childrenInvoker(final RunNotifier notifier) {
return new Statement() {
@Override
public void evaluate() {
JUnit4StoryReporter reporter = new JUnit4StoryReporter(notifier, description,
configuration.keywords());
// tell the reporter how to handle pending steps
reporter.usePendingStepStrategy(configuration.pendingStepStrategy());
addToStoryReporterFormats(reporter);
configurableEmbedder.run();
}
};
}
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);
}
private List<CandidateSteps> getCandidateSteps() {
InjectableStepsFactory stepsFactory = configurableEmbedder.stepsFactory();
if (stepsFactory != null) {
return stepsFactory.createCandidateSteps();
}
return configuredEmbedder.stepsFactory().createCandidateSteps();
}
private void addToStoryReporterFormats(StoryReporter reporter) {
StoryReporterBuilder storyReporterBuilder = configuration.storyReporterBuilder();
storyReporterBuilder.withFormats(new StoryReporterBuilder.ProvidedFormat(reporter));
}
private List<Description> buildDescriptionsFromStories(List<String> storyPaths) {
List<CandidateSteps> candidateSteps = getCandidateSteps();
AllStepCandidates allStepCandidates = new AllStepCandidates(configuration.stepConditionMatcher(),
candidateSteps);
JUnit4DescriptionGenerator descriptionGenerator = new JUnit4DescriptionGenerator(allStepCandidates,
configuration);
List<Description> storyDescriptions = new ArrayList<>();
addSuite(storyDescriptions, "BeforeStories");
PerformableTree performableTree = createPerformableTree(allStepCandidates, storyPaths);
storyDescriptions.addAll(descriptionGenerator.createDescriptionsFrom(performableTree));
addSuite(storyDescriptions, "AfterStories");
numberOfTestCases += descriptionGenerator.getTestCases();
return storyDescriptions;
}
private PerformableTree createPerformableTree(AllStepCandidates allStepCandidates,
List<String> storyPaths) {
BatchFailures failures = new BatchFailures(configuredEmbedder.embedderControls().verboseFailures());
PerformableTree performableTree = configuredEmbedder.performableTree();
RunContext context = performableTree.newRunContext(configuration, allStepCandidates,
configuredEmbedder.embedderMonitor(), configuredEmbedder.metaFilter(), failures);
performableTree.addStories(context, configuredEmbedder.storyManager().storiesOfPaths(storyPaths));
return performableTree;
}
private void addSuite(List<Description> storyDescriptions, String name) {
storyDescriptions.add(Description.createTestDescription(Object.class, name));
numberOfTestCases++;
}
}