Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JUnitFormatter: use ascending numbering of outline scenarios #706

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions core/src/main/java/cucumber/runtime/formatter/JUnitFormatter.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ public JUnitFormatter(URL out) throws IOException {
@Override
public void feature(Feature feature) {
TestCase.feature = feature;
TestCase.previousScenarioOutlineName = "";
TestCase.exampleNumber = 1;
}

@Override
Expand Down Expand Up @@ -194,7 +196,6 @@ public void scenarioOutline(ScenarioOutline scenarioOutline) {

@Override
public void examples(Examples examples) {
TestCase.examples = examples.getRows().size() - 1;
}

@Override
Expand Down Expand Up @@ -246,7 +247,8 @@ private TestCase() {

Scenario scenario;
static Feature feature;
static int examples = 0;
static String previousScenarioOutlineName;
static int exampleNumber;
static boolean treatSkippedAsFailure = false;
final List<Step> steps = new ArrayList<Step>();
final List<Result> results = new ArrayList<Result>();
Expand All @@ -258,7 +260,22 @@ private Element createElement(Document doc) {

private void writeElement(Document doc, Element tc) {
tc.setAttribute("classname", feature.getName());
tc.setAttribute("name", examples > 0 ? scenario.getName() + "_" + examples-- : scenario.getName());
tc.setAttribute("name", calculateElementName(scenario));
}

private String calculateElementName(Scenario scenario) {
String scenarioName = scenario.getName();
if (scenario.getKeyword().equals("Scenario Outline") && scenarioName.equals(previousScenarioOutlineName)) {
return scenarioName + (includesBlank(scenarioName) ? " " : "_") + ++exampleNumber;
} else {
previousScenarioOutlineName = scenario.getKeyword().equals("Scenario Outline") ? scenarioName : "";
exampleNumber = 1;
return scenarioName;
}
}

private boolean includesBlank(String scenarioName) {
return scenarioName.indexOf(' ') != -1;
}

public void updateElement(Document doc, Element tc) {
Expand Down
180 changes: 180 additions & 0 deletions core/src/test/java/cucumber/runtime/formatter/JUnitFormatterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,181 @@ public void should_accumulate_time_from_steps_and_hooks() throws Throwable {
assertXmlEqual(expected, formatterOutput);
}

@Test
public void should_format_scenario_outlines() throws Throwable {
CucumberFeature feature = TestHelper.feature("path/test.feature",
"Feature: feature name\n" +
" Scenario Outline: outline_name\n" +
" Given first step \"<arg>\"\n" +
" When second step\n" +
" Then third step\n\n" +
" Examples: examples\n" +
" | arg |\n" +
" | a |\n" +
" | b |\n");
Map<String, String> stepsToResult = new HashMap<String, String>();
stepsToResult.put("first step", "passed");
stepsToResult.put("second step", "passed");
stepsToResult.put("third step", "passed");
long stepDuration = milliSeconds(1);

String formatterOutput = runFeatureWithJUnitFormatter(feature, stepsToResult, stepDuration);

String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<testsuite failures=\"0\" name=\"cucumber.runtime.formatter.JUnitFormatter\" skipped=\"0\" tests=\"2\" time=\"0.006\">\n" +
" <testcase classname=\"feature name\" name=\"outline_name\" time=\"0.003\">\n" +
" <system-out><![CDATA[" +
"Given first step \"a\"........................................................passed\n" +
"When second step............................................................passed\n" +
"Then third step.............................................................passed\n" +
"]]></system-out>\n" +
" </testcase>\n" +
" <testcase classname=\"feature name\" name=\"outline_name_2\" time=\"0.003\">\n" +
" <system-out><![CDATA[" +
"Given first step \"b\"........................................................passed\n" +
"When second step............................................................passed\n" +
"Then third step.............................................................passed\n" +
"]]></system-out>\n" +
" </testcase>\n" +
"</testsuite>\n";
assertXmlEqual(expected, formatterOutput);
}

@Test
public void should_format_scenario_outlines_with_multiple_examples() throws Throwable {
CucumberFeature feature = TestHelper.feature("path/test.feature",
"Feature: feature name\n" +
" Scenario Outline: outline name\n" +
" Given first step \"<arg>\"\n" +
" When second step\n" +
" Then third step\n\n" +
" Examples: examples 1\n" +
" | arg |\n" +
" | a |\n" +
" | b |\n\n" +
" Examples: examples 2\n" +
" | arg |\n" +
" | c |\n" +
" | d |\n");
Map<String, String> stepsToResult = new HashMap<String, String>();
stepsToResult.put("first step", "passed");
stepsToResult.put("second step", "passed");
stepsToResult.put("third step", "passed");
long stepDuration = milliSeconds(1);

String formatterOutput = runFeatureWithJUnitFormatter(feature, stepsToResult, stepDuration);

String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<testsuite failures=\"0\" name=\"cucumber.runtime.formatter.JUnitFormatter\" skipped=\"0\" tests=\"4\" time=\"0.012\">\n" +
" <testcase classname=\"feature name\" name=\"outline name\" time=\"0.003\">\n" +
" <system-out><![CDATA[" +
"Given first step \"a\"........................................................passed\n" +
"When second step............................................................passed\n" +
"Then third step.............................................................passed\n" +
"]]></system-out>\n" +
" </testcase>\n" +
" <testcase classname=\"feature name\" name=\"outline name 2\" time=\"0.003\">\n" +
" <system-out><![CDATA[" +
"Given first step \"b\"........................................................passed\n" +
"When second step............................................................passed\n" +
"Then third step.............................................................passed\n" +
"]]></system-out>\n" +
" </testcase>\n" +
" <testcase classname=\"feature name\" name=\"outline name 3\" time=\"0.003\">\n" +
" <system-out><![CDATA[" +
"Given first step \"c\"........................................................passed\n" +
"When second step............................................................passed\n" +
"Then third step.............................................................passed\n" +
"]]></system-out>\n" +
" </testcase>\n" +
" <testcase classname=\"feature name\" name=\"outline name 4\" time=\"0.003\">\n" +
" <system-out><![CDATA[" +
"Given first step \"d\"........................................................passed\n" +
"When second step............................................................passed\n" +
"Then third step.............................................................passed\n" +
"]]></system-out>\n" +
" </testcase>\n" +
"</testsuite>\n";
assertXmlEqual(expected, formatterOutput);
}

@Test
public void should_format_scenario_outlines_with_arguments_in_name() throws Throwable {
CucumberFeature feature = TestHelper.feature("path/test.feature",
"Feature: feature name\n" +
" Scenario Outline: outline name <arg>\n" +
" Given first step \"<arg>\"\n" +
" When second step\n" +
" Then third step\n\n" +
" Examples: examples 1\n" +
" | arg |\n" +
" | a |\n" +
" | b |\n");
Map<String, String> stepsToResult = new HashMap<String, String>();
stepsToResult.put("first step", "passed");
stepsToResult.put("second step", "passed");
stepsToResult.put("third step", "passed");
long stepDuration = milliSeconds(1);

String formatterOutput = runFeatureWithJUnitFormatter(feature, stepsToResult, stepDuration);

String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<testsuite failures=\"0\" name=\"cucumber.runtime.formatter.JUnitFormatter\" skipped=\"0\" tests=\"2\" time=\"0.006\">\n" +
" <testcase classname=\"feature name\" name=\"outline name a\" time=\"0.003\">\n" +
" <system-out><![CDATA[" +
"Given first step \"a\"........................................................passed\n" +
"When second step............................................................passed\n" +
"Then third step.............................................................passed\n" +
"]]></system-out>\n" +
" </testcase>\n" +
" <testcase classname=\"feature name\" name=\"outline name b\" time=\"0.003\">\n" +
" <system-out><![CDATA[" +
"Given first step \"b\"........................................................passed\n" +
"When second step............................................................passed\n" +
"Then third step.............................................................passed\n" +
"]]></system-out>\n" +
" </testcase>\n" +
"</testsuite>\n";
assertXmlEqual(expected, formatterOutput);
}

@Test
public void should_format_scenario_outlines_with_the_junit_runner() throws Exception {
final File report = File.createTempFile("cucumber-jvm-junit", ".xml");
final JUnitFormatter junitFormatter = createJUnitFormatter(report);

// The JUnit runner will not call scenarioOutline() and examples() before executing the examples scenarios
junitFormatter.uri(uri());
junitFormatter.feature(feature("feature name"));
junitFormatter.scenario(scenario("Scenario Outline", "outline name"));
junitFormatter.step(step("keyword ", "step name \"arg1\""));
junitFormatter.match(match());
junitFormatter.result(result("passed"));
junitFormatter.scenario(scenario("Scenario Outline", "outline name"));
junitFormatter.step(step("keyword ", "step name \"arg2\""));
junitFormatter.match(match());
junitFormatter.result(result("passed"));
junitFormatter.eof();
junitFormatter.done();
junitFormatter.close();

String actual = new Scanner(new FileInputStream(report), "UTF-8").useDelimiter("\\A").next();
String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<testsuite failures=\"0\" tests=\"2\" name=\"cucumber.runtime.formatter.JUnitFormatter\" skipped=\"0\" time=\"0\">\n" +
" <testcase classname=\"feature name\" name=\"outline name\" time=\"0\">\n" +
" <system-out><![CDATA[" +
"keyword step name \"arg1\"....................................................passed\n" +
"]]></system-out>\n" +
" </testcase>\n" +
" <testcase classname=\"feature name\" name=\"outline name 2\" time=\"0\">\n" +
" <system-out><![CDATA[" +
"keyword step name \"arg2\"....................................................passed\n" +
"]]></system-out>\n" +
" </testcase>\n" +
"</testsuite>\n";
assertXmlEqual(expected, actual);
}

@Test
public void should_handle_all_step_calls_first_execution() throws Exception {
final File report = File.createTempFile("cucumber-jvm-junit", ".xml");
Expand Down Expand Up @@ -432,8 +607,13 @@ private Feature feature(String featureName) {
}

private Scenario scenario(String scenarioName) {
return scenario("Scenario", scenarioName);
}

private Scenario scenario(String keyword, String scenarioName) {
Scenario scenario = mock(Scenario.class);
when(scenario.getName()).thenReturn(scenarioName);
when(scenario.getKeyword()).thenReturn(keyword);
return scenario;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ public StepMatcher(String name) {

@Override
public boolean matches(Object argument) {
return argument instanceof Step && nameToMatch.endsWith(((Step)argument).getName());
return argument instanceof Step && (((Step)argument).getName().contains(nameToMatch));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ When step_2.................................................................unde
Then step_3.................................................................undefined
]]></skipped>
</testcase>
<testcase classname="Feature_3" name="ScenarioOutline_1_2" time="0">
<testcase classname="Feature_3" name="ScenarioOutline_1" time="0">
<skipped><![CDATA[Given bg_1..................................................................undefined
When bg_2...................................................................undefined
Then bg_3...................................................................undefined
Expand All @@ -18,7 +18,7 @@ When so_2 7 cucumbers.......................................................unde
Then 5 so_3.................................................................undefined
]]></skipped>
</testcase>
<testcase classname="Feature_3" name="ScenarioOutline_1_1" time="0">
<testcase classname="Feature_3" name="ScenarioOutline_1_2" time="0">
<skipped><![CDATA[Given bg_1..................................................................undefined
When bg_2...................................................................undefined
Then bg_3...................................................................undefined
Expand Down