package org.jbehave.core.parsers;
import static java.util.Arrays.asList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.jbehave.core.annotations.AfterScenario.Outcome;
import org.jbehave.core.configuration.Keywords;
import org.jbehave.core.i18n.LocalizedKeywords;
import org.jbehave.core.model.Description;
import org.jbehave.core.model.ExamplesTable;
import org.jbehave.core.model.GivenStories;
import org.jbehave.core.model.GivenStory;
import org.jbehave.core.model.Lifecycle;
import org.jbehave.core.model.Meta;
import org.jbehave.core.model.Narrative;
import org.jbehave.core.model.Scenario;
import org.jbehave.core.model.Story;
import org.jbehave.core.model.TableTransformers;
import org.junit.Test;
public class RegexStoryParserBehaviour {
private static final String NL = "\n";
private StoryParser parser = new RegexStoryParser(new LocalizedKeywords(), new TableTransformers());
private String storyPath = "path/to/my.story";
@Test
public void shouldParseStoryAndProvideNameFromPath() {
Story story = parser.parseStory("", storyPath);
assertThat(story.getPath(), equalTo(storyPath));
assertThat(story.getName(), equalTo(new File(storyPath).getName()));
}
@Test
public void shouldParseStoryAndProvideEmptyNameWhenPathIsNull() {
Story story = parser.parseStory("", null);
assertThat(story.getPath(), equalTo(""));
assertThat(story.getName(), equalTo(story.getPath()));
}
@Test
public void shouldParseStoryWithMetaAndGivenStories() {
String wholeStory = "Meta: @skip @theme parsing" + NL +
"GivenStories: path1,path2 " + NL +
"Scenario: A scenario" + NL +
"Meta: @author Mauro" + NL +
"Given a step " + NL +
"Scenario: Another scenario" + NL +
"Meta: @author Paul" + NL +
"Given another step ";
Story story = parser.parseStory(
wholeStory, storyPath);
assertThat(story.getPath(), equalTo(storyPath));
Meta storyMeta = story.getMeta();
assertThat(storyMeta.getProperty("theme"), equalTo("parsing"));
assertThat(storyMeta.getProperty("skip"), equalTo(""));
assertThat(storyMeta.getProperty("unknown"), equalTo(""));
assertThat(story.getGivenStories().getPaths(), equalTo(asList("path1", "path2")));
List<Scenario> scenarios = story.getScenarios();
assertThat(scenarios.get(0).getTitle(), equalTo("A scenario"));
assertThat(scenarios.get(0).getMeta().getProperty("author"), equalTo("Mauro"));
assertThat(scenarios.get(1).getTitle(), equalTo("Another scenario"));
assertThat(scenarios.get(1).getMeta().getProperty("author"), equalTo("Paul"));
}
@Test
public void shouldParseStoryWithMetaAndLifecycle() {
String wholeStory = "Meta: @skip @theme parsing" + NL +
"Lifecycle:" + NL +
"Before:" + NL +
"Given a step before each scenario" + NL +
"And another before step" + NL +
"Scenario: A scenario" + NL +
"Meta: @author Mauro" + NL +
"Given a step " + NL +
"Scenario: Another scenario" + NL +
"Meta: @author Paul" + NL +
"Given another step ";
Story story = parser.parseStory(
wholeStory, storyPath);
assertThat(story.getPath(), equalTo(storyPath));
Meta storyMeta = story.getMeta();
assertThat(storyMeta.getProperty("theme"), equalTo("parsing"));
assertThat(storyMeta.getProperty("skip"), equalTo(""));
assertThat(storyMeta.getProperty("unknown"), equalTo(""));
Lifecycle lifecycle = story.getLifecycle();
assertThat(lifecycle.getBeforeSteps().size(), equalTo(2));
List<Scenario> scenarios = story.getScenarios();
assertThat(scenarios.get(0).getTitle(), equalTo("A scenario"));
assertThat(scenarios.get(0).getMeta().getProperty("author"), equalTo("Mauro"));
assertThat(scenarios.get(1).getTitle(), equalTo("Another scenario"));
assertThat(scenarios.get(1).getMeta().getProperty("author"), equalTo("Paul"));
}
@Test
public void shouldParseStoryWithMetaAndNarrative() {
String wholeStory = "Meta: @skip @theme parsing" + NL +
"Narrative: This bit of text is ignored" + NL +
"In order to renovate my house" + NL +
"As a customer" + NL +
"I want to get a loan" + NL +
"Scenario: A scenario" + NL +
"Meta: @author Mauro" + NL +
"Given a step " + NL +
"Scenario: Another scenario" + NL +
"Meta: @author Paul" + NL +
"Given another step ";
Story story = parser.parseStory(
wholeStory, storyPath);
assertThat(story.getPath(), equalTo(storyPath));
Meta storyMeta = story.getMeta();
assertThat(storyMeta.getProperty("theme"), equalTo("parsing"));
assertThat(storyMeta.getProperty("skip"), equalTo(""));
assertThat(storyMeta.getProperty("unknown"), equalTo(""));
Narrative narrative = story.getNarrative();
assertThat(narrative.isEmpty(), not(true));
List<Scenario> scenarios = story.getScenarios();
assertThat(scenarios.get(0).getTitle(), equalTo("A scenario"));
assertThat(scenarios.get(0).getMeta().getProperty("author"), equalTo("Mauro"));
assertThat(scenarios.get(1).getTitle(), equalTo("Another scenario"));
assertThat(scenarios.get(1).getMeta().getProperty("author"), equalTo("Paul"));
}
@Test
public void shouldParseStoryWithGivenStoriesWithAnchorParameters() {
String wholeStory = "GivenStories: path1#{id1:scenario1;id2:scenario2}" + NL +
"Scenario: A scenario" + NL +
"Given a step";
Story story = parser.parseStory(
wholeStory, storyPath);
assertThat(story.getPath(), equalTo(storyPath));
assertThat(story.getGivenStories().getStories().size(), equalTo(1));
GivenStory givenStory = story.getGivenStories().getStories().get(0);
assertThat(givenStory.hasAnchorParameters(), equalTo(true));
Map<String, String> anchorParameters = givenStory.getAnchorParameters();
assertThat(anchorParameters.size(), equalTo(2));
assertThat(anchorParameters.get("id1"), equalTo("scenario1"));
assertThat(anchorParameters.get("id2"), equalTo("scenario2"));
}
@Test
public void shouldAllowSpacesInMetaProperties() {
String wholeStory = "Meta: @ theme parsing @ skip" + NL +
"Scenario: " + NL +
"Meta: @authors Mauro Paul" + NL +
"Given a scenario " + NL +
"When I parse it" + NL +
"Then I should get steps";
Story story = parser.parseStory(
wholeStory, storyPath);
assertThat(story.getPath(), equalTo(storyPath));
Meta storyMeta = story.getMeta();
assertThat(storyMeta.getProperty("theme"), equalTo("parsing"));
assertThat(storyMeta.getProperty("skip"), equalTo(""));
assertThat(story.getScenarios().get(0).getMeta().getProperty("authors"), equalTo("Mauro Paul"));
}
@Test
public void shouldIgnoreCommentsInMetaProperties() {
String wholeStory = "Meta: !-- this is the theme @theme parsing !-- skip me @skip" + NL +
"Scenario: " + NL +
"Meta: !-- these are the authors @authors Mauro Paul" + NL +
"Given a scenario " + NL +
"When I parse it" + NL +
"Then I should get steps";
Story story = parser.parseStory(
wholeStory, storyPath);
assertThat(story.getPath(), equalTo(storyPath));
Meta storyMeta = story.getMeta();
assertThat(storyMeta.getProperty("theme"), equalTo("parsing"));
assertThat(storyMeta.getProperty("skip"), equalTo(""));
assertThat(story.getScenarios().get(0).getMeta().getProperty("authors"), equalTo("Mauro Paul"));
}
@Test
public void shouldParseStoryWithSimpleSteps() {
String wholeStory = "Given a scenario" + NL +
"!-- ignore me" + NL +
"When I parse it" + NL +
"Then I should get steps";
Story story = parser.parseStory(
wholeStory, storyPath);
assertThat(story.getPath(), equalTo(storyPath));
List<String> steps = story.getScenarios().get(0).getSteps();
assertThat(steps.get(0), equalTo("Given a scenario"));
assertThat(steps.get(1), equalTo("!-- ignore me"));
assertThat(steps.get(2), equalTo("When I parse it"));
assertThat(steps.get(3), equalTo("Then I should get steps"));
}
@Test
public void shouldParseStoryWithStepsContainingKeywordsAtStartOfOtherWords() {
String wholeStory = "Meta: @some" + NL +
"Given a scenario Givenly" + NL +
"When I parse it to Whenever" + NL +
"And I parse it to Anderson" + NL +
"!-- ignore me too" + NL +
"Then I should get steps Thenact";
Story story = parser.parseStory(
wholeStory, storyPath);
List<String> steps = story.getScenarios().get(0).getSteps();
assertThat(steps.get(0), equalTo("Given a scenario Givenly"));
assertThat(steps.get(1), equalTo("When I parse it to Whenever"));
assertThat(steps.get(2), equalTo("And I parse it to Anderson"));
assertThat(steps.get(3), equalTo("!-- ignore me too"));
assertThat(steps.get(4), equalTo("Then I should get steps Thenact"));
}
@Test
public void shouldParseStoryWithSynonymsOfStartingWords() {
StoryParser parser = new RegexStoryParser(new LocalizedKeywords(new Locale("sy")), new TableTransformers());
String wholeStory = "Given a scenario" + NL +
"When I parse it" + NL +
"And I parse it again" + NL +
"With another parse as well" + NL +
"!-- ignore me" + NL +
"Giveth another scenario" + NL +
"With a merry go round";
Story story = parser.parseStory(
wholeStory, storyPath);
List<String> steps = story.getScenarios().get(0).getSteps();
assertThat(steps.get(0), equalTo("Given a scenario"));
assertThat(steps.get(1), equalTo("When I parse it"));
assertThat(steps.get(2), equalTo("And I parse it again"));
assertThat(steps.get(3), equalTo("With another parse as well"));
assertThat(steps.get(4), equalTo("!-- ignore me"));
assertThat(steps.get(5), equalTo("Giveth another scenario"));
assertThat(steps.get(6), equalTo("With a merry go round"));
}
@Test
public void shouldParseStoryWithGivenStoriesAtStoryAndScenarioLevel() {
String wholeStory = "GivenStories: GivenAPreconditionToStory" + NL +
"Scenario:"+ NL +
"GivenStories: GivenAPreconditionToScenario" + NL +
"Given a scenario Given";
Story story = parser.parseStory(wholeStory, storyPath);
assertThat(story.getGivenStories().getPaths(), equalTo(asList("GivenAPreconditionToStory")));
Scenario scenario = story.getScenarios().get(0);
assertThat(scenario.getGivenStories().getPaths(), equalTo(asList("GivenAPreconditionToScenario")));
List<String> steps = scenario.getSteps();
assertThat(steps.get(0), equalTo("Given a scenario Given"));
}
@Test
public void shouldParseStoryWithScenarioTitleGivenStoriesAndStepsContainingKeywordsNotAtStartOfLine() {
String wholeStory = "Scenario: Show that we have Given/When/Then as part of description or step content"+ NL +
"GivenStories: GivenAStoryContainingAKeyword" + NL +
"Given a scenario Given" + NL +
"When I parse it to When" + NL +
"And I parse it to And" + NL +
"!-- And ignore me too" + NL +
"Then I should get steps Then" + NL +
"Examples:" + NL +
"|Given|When|Then|And|" + NL +
"|Dato che|Quando|Allora|E|" + NL +
"|Dado que|Quando|Então|E|" + NL;
Story story = parser.parseStory(
wholeStory, storyPath);
Scenario scenario = story.getScenarios().get(0);
assertThat(scenario.getTitle(), equalTo("Show that we have Given/When/Then as part of description or step content"));
assertThat(scenario.getGivenStories().getPaths(), equalTo(asList("GivenAStoryContainingAKeyword")));
List<String> steps = scenario.getSteps();
assertThat(steps.get(0), equalTo("Given a scenario Given"));
assertThat(steps.get(1), equalTo("When I parse it to When"));
assertThat(steps.get(2), equalTo("And I parse it to And"));
assertThat(steps.get(3), equalTo("!-- And ignore me too"));
assertThat(steps.get(4), equalTo("Then I should get steps Then"));
assertThat(story.getScenarios().get(0).getExamplesTable().asString(),
equalTo("|Given|When|Then|And|" + NL +
"|Dato che|Quando|Allora|E|" + NL +
"|Dado que|Quando|Então|E|" + NL));
}
@Test
public void shouldParseStoryWithLifecycle() {
String wholeStory = "Lifecycle: " + NL +
"Before:" + NL + NL +
"Given a step before each scenario" + NL +
"And another before step" + NL +
"After:" + NL + NL +
"Given a step after each scenario" + NL +
"And another after step" + NL +
"Scenario:"+ NL +
"Given a scenario";
Story story = parser.parseStory(wholeStory, storyPath);
List<String> beforeSteps = story.getLifecycle().getBeforeSteps();
assertThat(beforeSteps.get(0), equalTo("Given a step before each scenario"));
assertThat(beforeSteps.get(1), equalTo("And another before step"));
List<String> afterSteps = story.getLifecycle().getAfterSteps();
assertThat(afterSteps.get(0), equalTo("Given a step after each scenario"));
assertThat(afterSteps.get(1), equalTo("And another after step"));
Scenario scenario = story.getScenarios().get(0);
List<String> steps = scenario.getSteps();
assertThat(steps.get(0), equalTo("Given a scenario"));
}
@Test
public void shouldParseStoryWithLifecycleBeforeOnly() {
String wholeStory = "Lifecycle: " + NL +
"Before:" + NL + NL +
"Given a step before each scenario" + NL +
"And another before step" + NL +
"Scenario:"+ NL +
"Given a scenario";
Story story = parser.parseStory(wholeStory, storyPath);
List<String> beforeSteps = story.getLifecycle().getBeforeSteps();
assertThat(beforeSteps.get(0), equalTo("Given a step before each scenario"));
assertThat(beforeSteps.get(1), equalTo("And another before step"));
List<String> afterSteps = story.getLifecycle().getAfterSteps();
assertThat(afterSteps.isEmpty(), equalTo(true));
Scenario scenario = story.getScenarios().get(0);
List<String> steps = scenario.getSteps();
assertThat(steps.get(0), equalTo("Given a scenario"));
}
@Test
public void shouldParseStoryWithLifecycleAfterOnly() {
String wholeStory = "Lifecycle: " + NL +
"After:" + NL + NL +
"Given a step after each scenario" + NL +
"And another after step" + NL +
"Scenario:"+ NL +
"Given a scenario";
Story story = parser.parseStory(wholeStory, storyPath);
List<String> beforeSteps = story.getLifecycle().getBeforeSteps();
assertThat(beforeSteps.isEmpty(), equalTo(true));
List<String> afterSteps = story.getLifecycle().getAfterSteps();
assertThat(afterSteps.get(0), equalTo("Given a step after each scenario"));
assertThat(afterSteps.get(1), equalTo("And another after step"));
Scenario scenario = story.getScenarios().get(0);
List<String> steps = scenario.getSteps();
assertThat(steps.get(0), equalTo("Given a scenario"));
}
@Test
public void shouldParseStoryWithLifecycleAfterUponOutcome() {
String wholeStory = "Lifecycle: " + NL +
"After:" + NL + NL +
"Outcome: ANY " + NL +
"Given a step after any scenario" + NL +
"Outcome: SUCCESS " + NL +
"Given a step after successful scenario" + NL +
"Outcome: FAILURE " + NL +
"Given a step after failed scenario" + NL +
"Scenario:"+ NL +
"Given a scenario";
Story story = parser.parseStory(wholeStory, storyPath);
List<String> beforeSteps = story.getLifecycle().getBeforeSteps();
assertThat(beforeSteps.isEmpty(), equalTo(true));
Lifecycle lifecycle = story.getLifecycle();
List<String> afterSteps = lifecycle.getAfterSteps();
assertThat(afterSteps.get(0), equalTo("Given a step after any scenario"));
assertThat(afterSteps.get(1), equalTo("Given a step after successful scenario"));
assertThat(afterSteps.get(2), equalTo("Given a step after failed scenario"));
assertThat(lifecycle.getAfterSteps(Outcome.ANY).size(), equalTo(1));
assertThat(lifecycle.getAfterSteps(Outcome.ANY).get(0), equalTo("Given a step after any scenario"));
assertThat(lifecycle.getAfterSteps(Outcome.SUCCESS).size(), equalTo(1));
assertThat(lifecycle.getAfterSteps(Outcome.SUCCESS).get(0), equalTo("Given a step after successful scenario"));
assertThat(lifecycle.getAfterSteps(Outcome.FAILURE).size(), equalTo(1));
assertThat(lifecycle.getAfterSteps(Outcome.FAILURE).get(0), equalTo("Given a step after failed scenario"));
Scenario scenario = story.getScenarios().get(0);
List<String> steps = scenario.getSteps();
assertThat(steps.get(0), equalTo("Given a scenario"));
}
@Test
public void shouldParseStoryWithLifecycleAfterUponOutcomeAndMetaFilter() {
String wholeStory = "Lifecycle: " + NL +
"After:" + NL + NL +
"Outcome: ANY " + NL +
"MetaFilter: +all" + NL +
"Given a step after any scenario" + NL +
"Outcome: SUCCESS " + NL +
"MetaFilter: +happy" + NL +
"Given a step after successful scenario" + NL +
"Outcome: FAILURE " + NL +
"MetaFilter: +sad" + NL +
"Given a step after failed scenario" + NL +
"Scenario:"+ NL +
"Given a scenario";
Story story = parser.parseStory(wholeStory, storyPath);
List<String> beforeSteps = story.getLifecycle().getBeforeSteps();
assertThat(beforeSteps.isEmpty(), equalTo(true));
Lifecycle lifecycle = story.getLifecycle();
List<String> afterSteps = lifecycle.getAfterSteps();
assertThat(afterSteps.get(0), equalTo("Given a step after any scenario"));
assertThat(afterSteps.get(1), equalTo("Given a step after successful scenario"));
assertThat(afterSteps.get(2), equalTo("Given a step after failed scenario"));
assertThat(new ArrayList<Outcome>(lifecycle.getOutcomes()), equalTo(Arrays.asList(Outcome.ANY, Outcome.SUCCESS, Outcome.FAILURE)));
assertThat(lifecycle.getAfterSteps(Outcome.ANY).size(), equalTo(1));
assertThat(lifecycle.getAfterSteps(Outcome.ANY).get(0), equalTo("Given a step after any scenario"));
assertThat(lifecycle.getAfterSteps(Outcome.SUCCESS).size(), equalTo(1));
assertThat(lifecycle.getAfterSteps(Outcome.SUCCESS).get(0), equalTo("Given a step after successful scenario"));
assertThat(lifecycle.getAfterSteps(Outcome.FAILURE).size(), equalTo(1));
assertThat(lifecycle.getAfterSteps(Outcome.FAILURE).get(0), equalTo("Given a step after failed scenario"));
assertThat(lifecycle.getMetaFilter(Outcome.ANY).asString(), equalTo("+all"));
Keywords keywords = new Keywords();
assertThat(lifecycle.getAfterSteps(Outcome.ANY, Meta.createMeta("@all", keywords)).size(), equalTo(1));
assertThat(lifecycle.getAfterSteps(Outcome.ANY, Meta.createMeta("@all", keywords)).get(0), equalTo("Given a step after any scenario"));
assertThat(lifecycle.getAfterSteps(Outcome.ANY, Meta.createMeta("@none", keywords)).size(), equalTo(0));
assertThat(lifecycle.getMetaFilter(Outcome.SUCCESS).asString(), equalTo("+happy"));
assertThat(lifecycle.getAfterSteps(Outcome.SUCCESS, Meta.createMeta("@happy", keywords)).size(), equalTo(1));
assertThat(lifecycle.getAfterSteps(Outcome.SUCCESS, Meta.createMeta("@happy", keywords)).get(0), equalTo("Given a step after successful scenario"));
assertThat(lifecycle.getAfterSteps(Outcome.SUCCESS, Meta.createMeta("@none", keywords)).size(), equalTo(0));
assertThat(lifecycle.getMetaFilter(Outcome.FAILURE).asString(), equalTo("+sad"));
assertThat(lifecycle.getAfterSteps(Outcome.FAILURE, Meta.createMeta("@sad", keywords)).size(), equalTo(1));
assertThat(lifecycle.getAfterSteps(Outcome.FAILURE, Meta.createMeta("@sad", keywords)).get(0), equalTo("Given a step after failed scenario"));
assertThat(lifecycle.getAfterSteps(Outcome.FAILURE, Meta.createMeta("@none", keywords)).size(), equalTo(0));
Scenario scenario = story.getScenarios().get(0);
List<String> steps = scenario.getSteps();
assertThat(steps.get(0), equalTo("Given a scenario"));
}
@Test
public void shouldParseStoryWithLifecycleAfterUponOutcomeInNonEnglishLocale() {
String wholeStory = "Lebenszyklus: " + NL +
"Nach:" + NL + NL +
"Ergebnis: JEDES " + NL +
"Gegeben im Lager sind 200 T-Shirts" + NL +
"Ergebnis: ERFOLG " + NL +
"Gegeben im Lager sind 300 T-Shirts" + NL +
"Ergebnis: FEHLER " + NL +
"Gegeben im Lager sind 400 T-Shirts" + NL +
"Szenario:"+ NL +
"Wenn ein Kunde 20 T-Shirts bestellt";
parser = new RegexStoryParser(new LocalizedKeywords(Locale.GERMAN), new TableTransformers());
Story story = parser.parseStory(wholeStory, storyPath);
List<String> beforeSteps = story.getLifecycle().getBeforeSteps();
assertThat(beforeSteps.isEmpty(), equalTo(true));
Lifecycle lifecycle = story.getLifecycle();
List<String> afterSteps = lifecycle.getAfterSteps();
assertThat(afterSteps.get(0), equalTo("Gegeben im Lager sind 200 T-Shirts"));
assertThat(afterSteps.get(1), equalTo("Gegeben im Lager sind 300 T-Shirts"));
assertThat(afterSteps.get(2), equalTo("Gegeben im Lager sind 400 T-Shirts"));
assertThat(lifecycle.getAfterSteps(Outcome.ANY).size(), equalTo(1));
assertThat(lifecycle.getAfterSteps(Outcome.ANY).get(0), equalTo("Gegeben im Lager sind 200 T-Shirts"));
assertThat(lifecycle.getAfterSteps(Outcome.SUCCESS).size(), equalTo(1));
assertThat(lifecycle.getAfterSteps(Outcome.SUCCESS).get(0), equalTo("Gegeben im Lager sind 300 T-Shirts"));
assertThat(lifecycle.getAfterSteps(Outcome.FAILURE).size(), equalTo(1));
assertThat(lifecycle.getAfterSteps(Outcome.FAILURE).get(0), equalTo("Gegeben im Lager sind 400 T-Shirts"));
Scenario scenario = story.getScenarios().get(0);
List<String> steps = scenario.getSteps();
assertThat(steps.get(0), equalTo("Wenn ein Kunde 20 T-Shirts bestellt"));
}
@Test
public void shouldParseStoryWithGivenStoriesAndExamplesCommentedOut() {
String wholeStory = "Scenario: Show that we can comment out GivenStories and Examples portions of a scenario"+ NL +
"!-- GivenStories: AGivenStoryToBeCommented" + NL +
"Given a scenario Given" + NL +
"When I parse it to When" + NL +
"And I parse it to And" + NL +
"!-- And ignore me too" + NL +
"Then I should get steps Then" + NL +
"!-- Examples:" + NL +
"|Comment|Me|Out|" + NL +
"|yes|we|can|" + NL;
Story story = parser.parseStory(
wholeStory, storyPath);
Scenario scenario = story.getScenarios().get(0);
assertThat(scenario.getTitle(), equalTo("Show that we can comment out GivenStories and Examples portions of a scenario"));
assertThat(scenario.getGivenStories().getPaths(), equalTo(Arrays.<String>asList()));
List<String> steps = scenario.getSteps();
assertThat(steps.get(0), equalTo("!-- GivenStories: AGivenStoryToBeCommented"));
assertThat(steps.get(1), equalTo("Given a scenario Given"));
assertThat(steps.get(2), equalTo("When I parse it to When"));
assertThat(steps.get(3), equalTo("And I parse it to And"));
assertThat(steps.get(4), equalTo("!-- And ignore me too"));
assertThat(steps.get(5), equalTo("Then I should get steps Then"));
assertThat(steps.get(6),
equalTo("!-- Examples:" + NL +
"|Comment|Me|Out|" + NL +
"|yes|we|can|"));
assertThat(scenario.getExamplesTable().asString(), equalTo(""));
}
@Test
public void shouldParseStoryWithMultilineSteps() {
String wholeStory = "Given a scenario" + NL +
"with this line" + NL +
"When I parse it" + NL +
"with another line" + NL + NL +
"Then I should get steps" + NL +
"without worrying about lines" + NL +
"or extra white space between or after steps" + NL + NL;
Story story = parser.parseStory(wholeStory, storyPath);
List<String> steps = story.getScenarios().get(0).getSteps();
assertThat(steps.get(0), equalTo("Given a scenario" + NL +
"with this line"));
assertThat(steps.get(1), equalTo("When I parse it" + NL +
"with another line"));
assertThat(steps.get(2), equalTo("Then I should get steps" + NL +
"without worrying about lines" + NL +
"or extra white space between or after steps"));
}
@Test
public void shouldParseStoryWithMultilineScenarioTitle() {
String wholeStory = "Scenario: A title\n that is spread across\n multiple lines" + NL + NL +
"Given a step that's pending" + NL +
"When I run the scenario" + NL +
"Then I should see this in the output";
Story story = parser.parseStory(wholeStory, null);
assertThat(story.getScenarios().get(0).getTitle(), equalTo("A title\n that is spread across\n multiple lines"));
}
@Test
public void shouldParseWithMultipleScenarios() {
String wholeStory = "Scenario: the first scenario " + NL + NL +
"Given my scenario" + NL + NL +
"Scenario: the second scenario" + NL + NL +
"Given my second scenario";
Story story = parser.parseStory(wholeStory, storyPath);
assertThat(story.getScenarios().get(0).getTitle(), equalTo("the first scenario"));
assertThat(story.getScenarios().get(0).getSteps(), equalTo(asList("Given my scenario")));
assertThat(story.getScenarios().get(1).getTitle(), equalTo("the second scenario"));
assertThat(story.getScenarios().get(1).getSteps(), equalTo(asList("Given my second scenario")));
}
@Test
public void shouldParseStoryWithDescriptionAndNarrative() {
String wholeStory = "Story: This is free-text description"+ NL +
"Narrative: This bit of text is ignored" + NL +
"In order to renovate my house" + NL +
"As a customer" + NL +
"I want to get a loan" + NL +
"Scenario: A first scenario";
Story story = parser.parseStory(
wholeStory, storyPath);
Description description = story.getDescription();
assertThat(description.asString(), equalTo("Story: This is free-text description"));
Narrative narrative = story.getNarrative();
assertThat(narrative.isEmpty(), not(true));
assertThat(narrative.inOrderTo().toString(), equalTo("renovate my house"));
assertThat(narrative.asA().toString(), equalTo("customer"));
assertThat(narrative.iWantTo().toString(), equalTo("get a loan"));
}
@Test
public void shouldParseStoryWithAlternativeNarrative() {
String wholeStory = "Story: This is free-text description"+ NL +
"Narrative: This is an alternative narrative" + NL +
"As a customer" + NL +
"I want to get a loan" + NL +
"So that I can renovate my house" + NL +
"Scenario: A first scenario";
Story story = parser.parseStory(
wholeStory, storyPath);
Description description = story.getDescription();
assertThat(description.asString(), equalTo("Story: This is free-text description"));
Narrative narrative = story.getNarrative();
assertThat(narrative.isEmpty(), not(true));
assertThat(narrative.asA().toString(), equalTo("customer"));
assertThat(narrative.iWantTo().toString(), equalTo("get a loan"));
assertThat(narrative.soThat().toString(), equalTo("I can renovate my house"));
}
@Test
public void shouldParseStoryWithIncompleteNarrative() {
String wholeStory = "Story: This is free-text description"+ NL +
"Narrative: This is an incomplete narrative" + NL +
"In order to renovate my house" + NL +
"As a customer" + NL +
"Scenario: A first scenario";
Story story = parser.parseStory(
wholeStory, storyPath);
Description description = story.getDescription();
assertThat(description.asString(), equalTo("Story: This is free-text description"));
Narrative narrative = story.getNarrative();
assertThat(narrative.isEmpty(), is(true));
}
@Test
public void shouldParseStoryWithAllElements() {
String wholeStory = "This is just a story description" + NL + NL +
"Narrative: " + NL +
"In order to see what we're not delivering" + NL + NL +
"As a developer" + NL +
"I want to see the narrative for my story when a scenario in that story breaks" + NL +
"GivenStories: path1,path2" + NL + NL +
"Lifecycle: " + NL +
"Before: " + NL + NL+
"Given a setup step" + NL +
"After: " + NL + NL+
"Then a teardown step" + NL +
"Scenario: A pending scenario" + NL + NL +
"Given a step that's pending" + NL +
"When I run the scenario" + NL +
"!-- A comment between steps" + NL +
"Then I should see this in the output" + NL +
"Scenario: A passing scenario" + NL +
"Given I'm not reporting passing stories" + NL +
"When I run the scenario" + NL +
"Then this should not be in the output" + NL +
"Scenario: A failing scenario" + NL +
"Given a step that fails" + NL +
"When I run the scenario" + NL +
"Then I should see this in the output" + NL +
"And I should see this in the output" + NL;
Story story = parser.parseStory(wholeStory, storyPath);
assertThat(story.toString(), containsString("This is just a story description"));
assertThat(story.getDescription().asString(), equalTo("This is just a story description"));
assertThat(story.toString(), containsString("Narrative"));
assertThat(story.getNarrative().inOrderTo(), equalTo("see what we're not delivering"));
assertThat(story.getNarrative().asA(), equalTo("developer"));
assertThat(story.getNarrative().iWantTo(), equalTo("see the narrative for my story when a scenario in that story breaks"));
assertThat(story.getGivenStories().getPaths(), hasItem("path1"));
assertThat(story.getGivenStories().getPaths(), hasItem("path2"));
assertThat(story.toString(), containsString("Lifecycle"));
assertThat(story.getLifecycle().getBeforeSteps().size(), equalTo(1));
assertThat(story.getLifecycle().getBeforeSteps(), hasItem("Given a setup step"));
assertThat(story.getLifecycle().getAfterSteps().size(), equalTo(1));
assertThat(story.getLifecycle().getAfterSteps(), hasItem("Then a teardown step"));
Meta storyAsMeta = story.asMeta("story_");
assertThat(storyAsMeta.getProperty("story_path"), equalTo(story.getPath()));
assertThat(storyAsMeta.getProperty("story_description"), equalTo(story.getDescription().asString()));
assertThat(storyAsMeta.getProperty("story_narrative"), equalTo(story.getNarrative().toString()));
assertThat(story.toString(), containsString("A pending scenario"));
Scenario firstScenario = story.getScenarios().get(0);
assertThat(firstScenario.getTitle(), equalTo("A pending scenario"));
assertThat(firstScenario.getGivenStories().getPaths().size(), equalTo(0));
assertThat(firstScenario.getSteps(), equalTo(asList(
"Given a step that's pending",
"When I run the scenario",
"!-- A comment between steps",
"Then I should see this in the output"
)));
Meta scenarioAsMeta = firstScenario.asMeta("scenario_");
assertThat(scenarioAsMeta.getProperty("scenario_title"), equalTo(firstScenario.getTitle()));
assertThat(scenarioAsMeta.getProperty("scenario_givenStories"), equalTo(firstScenario.getGivenStories().asString()));
assertThat(scenarioAsMeta.getProperty("scenario_examplesTable"), equalTo(firstScenario.getExamplesTable().asString()));
assertThat(story.toString(), containsString("A passing scenario"));
Scenario secondScenario = story.getScenarios().get(1);
assertThat(secondScenario.getTitle(), equalTo("A passing scenario"));
assertThat(secondScenario.getGivenStories().getPaths().size(), equalTo(0));
assertThat(secondScenario.getSteps(), equalTo(asList(
"Given I'm not reporting passing stories",
"When I run the scenario",
"Then this should not be in the output"
)));
assertThat(story.toString(), containsString("A failing scenario"));
Scenario thirdScenario = story.getScenarios().get(2);
assertThat(thirdScenario.getTitle(), equalTo("A failing scenario"));
assertThat(thirdScenario.getGivenStories().getPaths().size(), equalTo(0));
assertThat(thirdScenario.getSteps(), equalTo(asList(
"Given a step that fails",
"When I run the scenario",
"Then I should see this in the output",
"And I should see this in the output"
)));
}
public void shouldParseStoryWithVeryLongStep() {
String scenario = aScenarioWithAVeryLongGivenStep();
ensureThatScenarioCanBeParsed(scenario);
}
private String aScenarioWithAVeryLongGivenStep() {
StringBuilder longScenarioBuilder = new StringBuilder()
.append("Given all these examples:" + NL)
.append("|one|two|three|" + NL);
int numberOfLinesInStep = 50;
for (int i = 0; i < numberOfLinesInStep; i++) {
longScenarioBuilder.append("|a|sample|line|" + NL);
}
longScenarioBuilder.append("When I do something" + NL);
longScenarioBuilder.append("Then something should happen" + NL);
return longScenarioBuilder.toString();
}
private void ensureThatScenarioCanBeParsed(String scenarioAsText) {
parser.parseStory(scenarioAsText);
}
@Test
public void shouldParseLongStory() {
String aGivenWhenThen =
"Given a step" + NL +
"When I run it" + NL +
"Then I should seen an output" + NL;
StringBuffer aScenario = new StringBuffer();
aScenario.append("Scenario: A long scenario").append(NL);
int numberOfGivenWhenThensPerScenario = 50;
for (int i = 0; i < numberOfGivenWhenThensPerScenario; i++) {
aScenario.append(aGivenWhenThen);
}
int numberOfScenarios = 100;
StringBuffer wholeStory = new StringBuffer();
wholeStory.append("Story: A very long story").append(NL);
for (int i = 0; i < numberOfScenarios; i++) {
wholeStory.append(aScenario).append(NL);
}
Story story = parser.parseStory(wholeStory.toString(), null);
assertThat(story.getScenarios().size(), equalTo(numberOfScenarios));
for (Scenario scenario : story.getScenarios()) {
assertThat(scenario.getSteps().size(), equalTo(numberOfGivenWhenThensPerScenario * 3));
}
}
@Test
public void shouldParseStoryWithScenarioContainingExamplesTable() {
String wholeStory = "Scenario: A scenario with examples table" + NL + NL +
"Given a step with a <one>" + NL +
"When I run the scenario of name <two>" + NL +
"Then I should see <three> in the output" + NL +
"Examples:" + NL +
"|one|two|three|" + NL +
"|11|12|13|" + NL +
"|21|22|23|" + NL;
Story story = parser.parseStory(wholeStory, storyPath);
Scenario scenario = story.getScenarios().get(0);
assertThat(scenario.getTitle(), equalTo("A scenario with examples table"));
assertThat(scenario.getGivenStories().getPaths().size(), equalTo(0));
assertThat(scenario.getSteps(), equalTo(asList(
"Given a step with a <one>",
"When I run the scenario of name <two>",
"Then I should see <three> in the output"
)));
ExamplesTable table = scenario.getExamplesTable();
assertThat(table.asString(), equalTo(
"|one|two|three|" + NL +
"|11|12|13|" + NL +
"|21|22|23|" + NL));
assertThat(table.getRowCount(), equalTo(2));
assertThat(table.getRow(0), not(nullValue()));
assertThat(table.getRow(0).get("one"), equalTo("11"));
assertThat(table.getRow(0).get("two"), equalTo("12"));
assertThat(table.getRow(0).get("three"), equalTo("13"));
assertThat(table.getRow(1), not(nullValue()));
assertThat(table.getRow(1).get("one"), equalTo("21"));
assertThat(table.getRow(1).get("two"), equalTo("22"));
assertThat(table.getRow(1).get("three"), equalTo("23"));
}
@Test
public void shouldParseStoryWithScenarioContainingGivenStories() {
// given stories as CSV with no spaces or newlines
parseStoryWithGivenStories(
"GivenStories: path/to/one,path/to/two" + NL + NL +
"Given a step");
// given stories as CSV with spaces and newlines
parseStoryWithGivenStories(
"GivenStories: path/to/one , "+ NL +" path/to/two" + NL + NL +
"Given a step");
}
@Test
public void shouldParseStoryWithScenarioContainingParametrisedGivenStories() {
String wholeStory =
"GivenStories: path/to/one#{0}, path/to/two#{1}, path/to/three#{2}, path/to/four#{a}, path/to/five" + NL + NL +
"Given a step" + NL+
"Examples:" + NL +
"|one|two|" + NL +
"|11|12|" + NL +
"|21|22|";
Story story = parser.parseStory(wholeStory, storyPath);
Scenario scenario = story.getScenarios().get(0);
GivenStories givenStories = scenario.getGivenStories();
assertThat(givenStories.asString(), equalTo("path/to/one#{0}, path/to/two#{1}, path/to/three#{2}, path/to/four#{a}, path/to/five"));
assertThat(givenStories.toString(), containsString(givenStories.asString()));
assertThat(givenStories.getPaths(), equalTo(asList(
"path/to/one#{0}", // matches first parameters row
"path/to/two#{1}", // matches second parameters row
"path/to/three#{2}", // does not match any parameters row
"path/to/four#{a}", // does not use valid anchor (an int)
"path/to/five"))); // does not require parameters
assertThat(givenStories.requireParameters(), equalTo(true));
GivenStory givenStory1 = givenStories.getStories().get(0);
assertThat(givenStory1.hasAnchor(), equalTo(true));
assertThat(givenStory1.getAnchor(), equalTo("0"));
assertThat(givenStory1.getPath(), equalTo("path/to/one"));
assertThat(givenStory1.getParameters().get("one"), equalTo("11"));
assertThat(givenStory1.getParameters().get("two"), equalTo("12"));
GivenStory givenStory2 = givenStories.getStories().get(1);
assertThat(givenStory2.hasAnchor(), equalTo(true));
assertThat(givenStory2.getAnchor(), equalTo("1"));
assertThat(givenStory2.getPath(), equalTo("path/to/two"));
assertThat(givenStory2.getParameters().get("one"), equalTo("21"));
assertThat(givenStory2.getParameters().get("two"), equalTo("22"));
GivenStory givenStory3 = givenStories.getStories().get(2);
assertThat(givenStory3.hasAnchor(), equalTo(true));
assertThat(givenStory3.getAnchor(), equalTo("2"));
assertThat(givenStory3.getPath(), equalTo("path/to/three"));
assertThat(givenStory3.getParameters().size(), equalTo(0));
GivenStory givenStory4 = givenStories.getStories().get(3);
assertThat(givenStory4.hasAnchor(), equalTo(true));
assertThat(givenStory4.getAnchor(), equalTo("a"));
assertThat(givenStory4.getPath(), equalTo("path/to/four"));
assertThat(givenStory4.getParameters().size(), equalTo(0));
GivenStory givenStory5 = givenStories.getStories().get(4);
assertThat(givenStory5.hasAnchor(), equalTo(false));
assertThat(givenStory5.getAnchor(), equalTo(""));
assertThat(givenStory5.getPath(), equalTo("path/to/five"));
assertThat(givenStory5.getParameters().size(), equalTo(0));
}
private void parseStoryWithGivenStories(String wholeStory) {
Story story = parser.parseStory(wholeStory, storyPath);
Scenario scenario = story.getScenarios().get(0);
assertThat(scenario.getGivenStories().getPaths(), equalTo(asList(
"path/to/one",
"path/to/two")));
assertThat(scenario.getSteps(), equalTo(asList(
"Given a step"
)));
}
@Test
public void shouldParseStoryWithoutAPath() {
String wholeStory = "Given a step" + NL +
"When I run it" + NL +
"Then I should an output";
Story story = parser.parseStory(wholeStory);
assertThat(story.getPath(), equalTo(""));
Scenario scenario = story.getScenarios().get(0);
assertThat(scenario.getSteps(), equalTo(asList(
"Given a step",
"When I run it",
"Then I should an output"
)));
}
@Test
public void shouldParseStoryWithVeryLongTitle() {
ensureThatScenarioCanBeParsed(aScenarioWithAVeryLongTitle(2000));
}
private String aScenarioWithAVeryLongTitle(int numberOfLines) {
StringBuilder builder = new StringBuilder();
builder.append("Scenario: First line of long title." + NL)
.append("After that follows a long textual description. " + NL);
for (int i = 0; i < numberOfLines; i++) {
builder.append("A line from the long description with about 60 characters." + NL);
}
builder.append("Given the first step that marks end of title" + NL);
return builder.toString();
}
@Test
public void shouldParseStoryWithVeryLongTables() {
ensureThatScenarioCanBeParsed(aScenarioWithVeryLongTables(2000));
}
private String aScenarioWithVeryLongTables(int numberOfLines) {
StringBuilder builder = new StringBuilder();
builder.append("Scenario: A scenario with long tables" + NL)
.append("GivenStories: path1,path2,path3" + NL);
builder.append("Given a step with a long tabular argument: " + NL)
.append(aTableWith(numberOfLines));
builder.append("Examples:" + NL)
.append(aTableWith(numberOfLines));
return builder.toString();
}
private String aTableWith(int numberOfLines) {
StringBuilder builder = new StringBuilder();
builder.append("|h0|h1|h2|h3|h4|h5|h6|h7|h8|h9|" + NL);
for (int i = 0; i < numberOfLines; i++) {
builder.append("|c"+i+"0|c"+i+"1|c"+i+"2|c"+i+"3|c"+i+"4|c"+i+"5|c"+i+"6|c"+i+"7|c"+i+"8|c"+i+"9|" + NL);
}
return builder.toString();
}
}