JUnit4DescriptionGenerator.java
- package org.jbehave.core.junit;
- import java.lang.annotation.Annotation;
- import java.lang.reflect.Method;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import java.util.function.Function;
- import org.jbehave.core.annotations.AfterScenario.Outcome;
- import org.jbehave.core.annotations.ScenarioType;
- import org.jbehave.core.annotations.Scope;
- import org.jbehave.core.configuration.Configuration;
- import org.jbehave.core.configuration.Keywords;
- import org.jbehave.core.embedder.AllStepCandidates;
- import org.jbehave.core.embedder.PerformableTree;
- import org.jbehave.core.embedder.PerformableTree.ExamplePerformableScenario;
- import org.jbehave.core.embedder.PerformableTree.PerformableScenario;
- import org.jbehave.core.embedder.PerformableTree.PerformableStory;
- import org.jbehave.core.model.GivenStories;
- import org.jbehave.core.model.Lifecycle;
- import org.jbehave.core.model.Scenario;
- import org.jbehave.core.model.Story;
- import org.jbehave.core.steps.BeforeOrAfterStep;
- import org.jbehave.core.steps.ConditionalStepCandidate;
- import org.jbehave.core.steps.StepCandidate;
- import org.jbehave.core.steps.StepType;
- import org.junit.runner.Description;
- public class JUnit4DescriptionGenerator {
- private final TextManipulator textManipulator = new TextManipulator();
- private final Configuration configuration;
- private final AllStepCandidates allStepCandidates;
- private String previousNonAndStep;
- private int testCases;
- private final JUnit4Test junitTestMeta;
- public JUnit4DescriptionGenerator(AllStepCandidates allStepCandidates, Configuration configuration) {
- this.configuration = configuration;
- this.allStepCandidates = allStepCandidates;
- this.junitTestMeta = new JUnit4Test() {
- @Override
- public Class<? extends Annotation> annotationType() {
- return JUnit4Test.class;
- }
- };
- }
- public List<Description> createDescriptionsFrom(PerformableTree performableTree) {
- List<Description> storyDescriptions = new ArrayList<>();
- for (PerformableStory performableStory : performableTree.getRoot().getStories()) {
- if (!performableStory.isExcluded()) {
- Story story = performableStory.getStory();
- Lifecycle lifecycle = story.getLifecycle();
- Description storyDescription = createDescriptionForStory(story);
- addBeforeOrAfterStep(allStepCandidates.getBeforeStorySteps(false), storyDescription,
- "@BeforeStory: ");
- addSteps(storyDescription, lifecycle.getBeforeSteps(Scope.STORY));
- if (story.hasGivenStories()) {
- insertGivenStories(story.getGivenStories(), storyDescription);
- }
- List<PerformableScenario> scenarios = performableStory.getScenarios();
- for (Description scenarioDescription : getScenarioDescriptions(lifecycle, scenarios)) {
- storyDescription.addChild(scenarioDescription);
- }
- addSteps(storyDescription, lifecycle.getAfterSteps(Scope.STORY, Outcome.ANY));
- addBeforeOrAfterStep(allStepCandidates.getAfterStorySteps(false), storyDescription,
- "@AfterStory: ");
- storyDescriptions.add(storyDescription);
- }
- }
- return storyDescriptions;
- }
- public Description createDescriptionsFrom(Lifecycle lifecycle, PerformableScenario performableScenario) {
- Scenario scenario = performableScenario.getScenario();
- Description scenarioDescription = createDescriptionForScenario(scenario);
- if (performableScenario.hasExamples() && !scenario.getGivenStories().requireParameters()) {
- insertDescriptionForExamples(lifecycle, performableScenario, scenarioDescription);
- } else {
- addScenarioSteps(lifecycle, ScenarioType.NORMAL, scenario, scenarioDescription);
- }
- return scenarioDescription;
- }
- private void addScenarioSteps(Lifecycle lifecycle, ScenarioType scenarioType, Scenario scenario,
- Description scenarioDescription) {
- addBeforeOrAfterScenarioStep(allStepCandidates::getBeforeScenarioSteps, scenarioType, scenarioDescription,
- "@BeforeScenario: ");
- addSteps(scenarioDescription, lifecycle.getBeforeSteps(Scope.SCENARIO));
- if (scenario.hasGivenStories()) {
- insertGivenStories(scenario.getGivenStories(), scenarioDescription);
- }
- addScenarioSteps(lifecycle, scenarioDescription, scenario);
- addSteps(scenarioDescription, lifecycle.getAfterSteps(Scope.SCENARIO, Outcome.ANY));
- addBeforeOrAfterScenarioStep(allStepCandidates::getAfterScenarioSteps, scenarioType, scenarioDescription,
- "@AfterScenario: ");
- }
- private void addScenarioSteps(Lifecycle lifecycle, Description scenarioDescription, Scenario scenario) {
- List<String> beforeSteps = lifecycle.getBeforeSteps(Scope.STEP);
- List<String> afterSteps = lifecycle.getAfterSteps(Scope.STEP);
- previousNonAndStep = null;
- String tempPreviousNonAndStep = null;
- for (String scenarioStep : scenario.getSteps()) {
- addSteps(scenarioDescription, beforeSteps);
- previousNonAndStep = tempPreviousNonAndStep;
- addStep(scenarioDescription, scenarioStep);
- tempPreviousNonAndStep = previousNonAndStep;
- addSteps(scenarioDescription, afterSteps);
- }
- }
- private void addBeforeOrAfterScenarioStep(Function<ScenarioType, List<BeforeOrAfterStep>> stepsProvider,
- ScenarioType scenarioType, Description description, String stepName) {
- List<BeforeOrAfterStep> beforeOrAfterSteps = new ArrayList<>();
- beforeOrAfterSteps.addAll(stepsProvider.apply(scenarioType));
- beforeOrAfterSteps.addAll(stepsProvider.apply(ScenarioType.ANY));
- addBeforeOrAfterStep(beforeOrAfterSteps, description, stepName);
- }
- private void addBeforeOrAfterStep(List<BeforeOrAfterStep> beforeOrAfterSteps, Description description,
- String stepPrefix) {
- beforeOrAfterSteps.forEach(steps -> {
- testCases++;
- Method method = steps.getMethod();
- String stepName = uniquify(stepPrefix + steps.getMethod().getName());
- Description testDescription = Description.createTestDescription(method.getDeclaringClass(), stepName,
- junitTestMeta);
- description.addChild(testDescription);
- });
- }
- public String uniquify(String string) {
- return textManipulator.uniquify(string);
- }
- public int getTestCases() {
- return testCases;
- }
- private void insertGivenStories(GivenStories givenStories, Description parentDescription) {
- for (String path : givenStories.getPaths()) {
- addGivenStory(parentDescription, path);
- }
- }
- private void addGivenStory(Description parentDescription, String path) {
- parentDescription.addChild(Description.createSuiteDescription(uniquify(getFilename(path)), junitTestMeta));
- testCases++;
- }
- private String getFilename(String path) {
- return path.substring(path.lastIndexOf('/') + 1).split("#")[0];
- }
- private void insertDescriptionForExamples(Lifecycle lifecycle, PerformableScenario performableScenario,
- Description scenarioDescription) {
- Scenario scenario = performableScenario.getScenario();
- for (ExamplePerformableScenario examplePerformableScenario : performableScenario.getExamples()) {
- Description exampleRowDescription = Description.createSuiteDescription(
- configuration.keywords().examplesTableRow() + " " + examplePerformableScenario.getParameters());
- scenarioDescription.addChild(exampleRowDescription);
- addScenarioSteps(lifecycle, ScenarioType.EXAMPLE, scenario, exampleRowDescription);
- }
- }
- private void addSteps(Description description, List<String> steps) {
- previousNonAndStep = null;
- steps.forEach(step -> addStep(description, step));
- }
- private void addStep(Description description, String step) {
- String stringStepOneLine = stripLinebreaks(step);
- StepCandidate matchingStep = findMatchingStep(step);
- if (matchingStep == null) {
- addNonExistingStep(description, stringStepOneLine, step);
- } else {
- addExistingStep(description, stringStepOneLine, matchingStep);
- }
- }
- private void addExistingStep(Description description, String stringStepOneLine, StepCandidate matchingStep) {
- if (matchingStep.isComposite()) {
- addCompositeSteps(description, stringStepOneLine, matchingStep);
- } else if (matchingStep instanceof ConditionalStepCandidate) {
- addConditionalStep(description, stringStepOneLine);
- } else {
- addRegularStep(description, stringStepOneLine, matchingStep);
- }
- }
- private void addNonExistingStep(Description description, String stringStepOneLine, String stepAsString) {
- Keywords keywords = configuration.keywords();
- if (keywords.isIgnorableStep(stepAsString)) {
- if (isStep(keywords.stepWithoutStartingWord(stepAsString, StepType.IGNORABLE))) {
- addIgnorableStep(description, stringStepOneLine);
- }
- } else {
- addPendingStep(description, stringStepOneLine);
- }
- }
- private boolean isStep(String stepAsString) {
- Keywords keywords = configuration.keywords();
- for (String stepStartingWord : keywords.startingWordsByType().values()) {
- if (keywords.stepStartsWithWord(stepAsString, stepStartingWord)) {
- return true;
- }
- }
- return false;
- }
- private void addIgnorableStep(Description description, String stringStep) {
- testCases++;
- description.addChild(Description.createSuiteDescription(stringStep));
- }
- private void addPendingStep(Description description, String stringStep) {
- testCases++;
- description.addChild(Description.createSuiteDescription(uniquify("[PENDING] " + stringStep)));
- }
- private void addConditionalStep(Description description, String stringStep) {
- testCases++;
- description.addChild(Description.createSuiteDescription(uniquify(stringStep)));
- }
- private void addRegularStep(Description description, String stringStep, StepCandidate step) {
- testCases++;
- // JUnit and the Eclipse JUnit view needs to be touched/fixed in order to make the JUnit view jump to the
- // corresponding test method accordingly. For now we have to live, that we end up in the correct class.
- description.addChild(Description.createTestDescription(step.getStepsType(), uniquify(stringStep),
- junitTestMeta));
- }
- private void addCompositeSteps(Description description, String stringStep, StepCandidate step) {
- Description testDescription = Description.createSuiteDescription(uniquify(stringStep), junitTestMeta);
- addSteps(testDescription, Arrays.asList(step.composedSteps()));
- description.addChild(testDescription);
- }
- private List<Description> getScenarioDescriptions(Lifecycle lifecycle,
- List<PerformableScenario> performableScenarios) {
- List<Description> scenarioDescriptions = new ArrayList<>();
- for (PerformableScenario scenario : performableScenarios) {
- if (!scenario.isExcluded()) {
- scenarioDescriptions.add(createDescriptionsFrom(lifecycle, scenario));
- }
- }
- return scenarioDescriptions;
- }
- private StepCandidate findMatchingStep(String stringStep) {
- for (StepCandidate step : allStepCandidates.getRegularSteps()) {
- if (step.matches(stringStep, previousNonAndStep)) {
- if (step.getStepType() != StepType.AND) {
- previousNonAndStep = step.getStartingWord() + " ";
- }
- return step;
- }
- }
- return null;
- }
- private String stripLinebreaks(String stringStep) {
- if (stringStep.indexOf('\n') != -1) {
- return stringStep.substring(0, stringStep.indexOf('\n'));
- }
- return stringStep;
- }
- private Description createDescriptionForStory(Story story) {
- return Description.createSuiteDescription(uniquify(story.getName()));
- }
- private Description createDescriptionForScenario(Scenario scenario) {
- return Description.createSuiteDescription(
- configuration.keywords().scenario() + " " + uniquify(scenario.getTitle()));
- }
- public @interface JUnit4Test {
- }
- }