JUnit4StoryRunner.java

  1. package org.jbehave.core.junit;

  2. import java.util.ArrayList;
  3. import java.util.List;

  4. import org.jbehave.core.ConfigurableEmbedder;
  5. import org.jbehave.core.configuration.Configuration;
  6. import org.jbehave.core.embedder.AllStepCandidates;
  7. import org.jbehave.core.embedder.Embedder;
  8. import org.jbehave.core.embedder.EmbedderControls;
  9. import org.jbehave.core.embedder.PerformableTree;
  10. import org.jbehave.core.embedder.PerformableTree.RunContext;
  11. import org.jbehave.core.failures.BatchFailures;
  12. import org.jbehave.core.reporters.StoryReporter;
  13. import org.jbehave.core.reporters.StoryReporterBuilder;
  14. import org.jbehave.core.steps.CandidateSteps;
  15. import org.jbehave.core.steps.InjectableStepsFactory;
  16. import org.jbehave.core.steps.NullStepMonitor;
  17. import org.jbehave.core.steps.StepMonitor;
  18. import org.junit.runner.Description;
  19. import org.junit.runner.notification.RunNotifier;
  20. import org.junit.runners.BlockJUnit4ClassRunner;
  21. import org.junit.runners.model.InitializationError;
  22. import org.junit.runners.model.Statement;

  23. public class JUnit4StoryRunner extends BlockJUnit4ClassRunner {
  24.     private final ConfigurableEmbedder configurableEmbedder;
  25.     private final Embedder configuredEmbedder;
  26.     private final Configuration configuration;
  27.     private final Description description;
  28.     private int numberOfTestCases;

  29.     public JUnit4StoryRunner(Class<? extends ConfigurableEmbedder> testClass)
  30.             throws InitializationError, ReflectiveOperationException {
  31.         super(testClass);
  32.         configurableEmbedder = testClass.getDeclaredConstructor().newInstance();
  33.         configuredEmbedder = configurableEmbedder.configuredEmbedder();
  34.         configuration = configuredEmbedder.configuration();

  35.         List<String> storyPaths = storyPathsFor(configurableEmbedder);

  36.         StepMonitor originalStepMonitor = configuration.stepMonitor();
  37.         configuration.useStepMonitor(new NullStepMonitor());
  38.         List<Description> storyDescriptions = buildDescriptionsFromStories(storyPaths);
  39.         configuration.useStepMonitor(originalStepMonitor);

  40.         description = Description.createSuiteDescription(testClass);
  41.         for (Description storyDescription : storyDescriptions) {
  42.             description.addChild(storyDescription);
  43.         }
  44.     }

  45.     private List<String> storyPathsFor(ConfigurableEmbedder configurableEmbedder) {
  46.         if (configurableEmbedder instanceof JUnitStories) {
  47.             return ((JUnitStories)configurableEmbedder).storyPaths();
  48.         }
  49.         throw new IllegalArgumentException(
  50.                 "Only ConfigurableEmbedder of type JUnitStories is supported");
  51.     }

  52.     @Override
  53.     public Description getDescription() {
  54.         return description;
  55.     }

  56.     @Override
  57.     public int testCount() {
  58.         return numberOfTestCases;
  59.     }

  60.     /**
  61.      * Returns a {@link Statement} execution the {@link ConfigurableEmbedder#run()}
  62.      * with a {@link JUnit4StoryReporter}.
  63.      */
  64.     @Override
  65.     protected Statement childrenInvoker(final RunNotifier notifier) {
  66.         return new Statement() {
  67.             @Override
  68.             public void evaluate() {
  69.                 JUnit4StoryReporter reporter = new JUnit4StoryReporter(notifier, description,
  70.                         configuration.keywords());
  71.                 // tell the reporter how to handle pending steps
  72.                 reporter.usePendingStepStrategy(configuration.pendingStepStrategy());

  73.                 addToStoryReporterFormats(reporter);

  74.                 configurableEmbedder.run();
  75.             }
  76.         };
  77.     }

  78.     public static EmbedderControls recommendedControls(Embedder embedder) {
  79.         return embedder.embedderControls()
  80.                 // don't throw an exception on generating reports for failing stories
  81.                 .doIgnoreFailureInView(true)
  82.                 // don't throw an exception when a story failed
  83.                 .doIgnoreFailureInStories(true);
  84.     }

  85.     private List<CandidateSteps> getCandidateSteps() {
  86.         InjectableStepsFactory stepsFactory = configurableEmbedder.stepsFactory();
  87.         if (stepsFactory != null) {
  88.             return stepsFactory.createCandidateSteps();
  89.         }
  90.         return configuredEmbedder.stepsFactory().createCandidateSteps();
  91.     }

  92.     private void addToStoryReporterFormats(StoryReporter reporter) {
  93.         StoryReporterBuilder storyReporterBuilder = configuration.storyReporterBuilder();
  94.         storyReporterBuilder.withFormats(new StoryReporterBuilder.ProvidedFormat(reporter));
  95.     }

  96.     private List<Description> buildDescriptionsFromStories(List<String> storyPaths) {
  97.         List<CandidateSteps> candidateSteps = getCandidateSteps();
  98.         AllStepCandidates allStepCandidates = new AllStepCandidates(configuration.stepConditionMatcher(),
  99.                 candidateSteps);
  100.         JUnit4DescriptionGenerator descriptionGenerator = new JUnit4DescriptionGenerator(allStepCandidates,
  101.                 configuration);
  102.         List<Description> storyDescriptions = new ArrayList<>();

  103.         addSuite(storyDescriptions, "BeforeStories");
  104.         PerformableTree performableTree = createPerformableTree(allStepCandidates, storyPaths);
  105.         storyDescriptions.addAll(descriptionGenerator.createDescriptionsFrom(performableTree));
  106.         addSuite(storyDescriptions, "AfterStories");

  107.         numberOfTestCases += descriptionGenerator.getTestCases();

  108.         return storyDescriptions;
  109.     }

  110.     private PerformableTree createPerformableTree(AllStepCandidates allStepCandidates,
  111.             List<String> storyPaths) {
  112.         BatchFailures failures = new BatchFailures(configuredEmbedder.embedderControls().verboseFailures());
  113.         PerformableTree performableTree = configuredEmbedder.performableTree();
  114.         RunContext context = performableTree.newRunContext(configuration, allStepCandidates,
  115.                 configuredEmbedder.embedderMonitor(), configuredEmbedder.metaFilter(), failures);
  116.         performableTree.addStories(context, configuredEmbedder.storyManager().storiesOfPaths(storyPaths));
  117.         return performableTree;
  118.     }

  119.     private void addSuite(List<Description> storyDescriptions, String name) {
  120.         storyDescriptions.add(Description.createTestDescription(Object.class, name));
  121.         numberOfTestCases++;
  122.     }
  123. }