package cucumber.runtime.formatter;
import cucumber.runtime.Backend;
import cucumber.runtime.Runtime;
import cucumber.runtime.RuntimeOptions;
import cucumber.runtime.TestHelper;
import cucumber.runtime.Utils;
import cucumber.runtime.io.ClasspathResourceLoader;
import cucumber.runtime.model.CucumberFeature;
import cucumber.runtime.snippets.FunctionNameGenerator;
import gherkin.formatter.model.Feature;
import gherkin.formatter.model.Match;
import gherkin.formatter.model.Result;
import gherkin.formatter.model.Scenario;
import gherkin.formatter.model.Step;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.XMLUnit;
import org.junit.Test;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import static cucumber.runtime.TestHelper.result;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class JUnitFormatterTest {
@Test
public void featureSimpleTest() throws Exception {
File report = runFeaturesWithJunitFormatter(asList("cucumber/runtime/formatter/JUnitFormatterTest_1.feature"));
assertXmlEqual("cucumber/runtime/formatter/JUnitFormatterTest_1.report.xml", report);
}
@Test
public void featureWithBackgroundTest() throws Exception {
File report = runFeaturesWithJunitFormatter(asList("cucumber/runtime/formatter/JUnitFormatterTest_2.feature"));
assertXmlEqual("cucumber/runtime/formatter/JUnitFormatterTest_2.report.xml", report);
}
@Test
public void featureWithOutlineTest() throws Exception {
File report = runFeaturesWithJunitFormatter(asList("cucumber/runtime/formatter/JUnitFormatterTest_3.feature"));
assertXmlEqual("cucumber/runtime/formatter/JUnitFormatterTest_3.report.xml", report);
}
@Test
public void featureSimpleStrictTest() throws Exception {
boolean strict = true;
File report = runFeaturesWithJunitFormatter(asList("cucumber/runtime/formatter/JUnitFormatterTest_1.feature"), strict);
assertXmlEqual("cucumber/runtime/formatter/JUnitFormatterTest_1_strict.report.xml", report);
}
@Test
public void should_format_passed_scenario() throws Throwable {
CucumberFeature feature = TestHelper.feature("path/test.feature",
"Feature: feature name\n" +
" Scenario: scenario name\n" +
" Given first step\n" +
" When second step\n" +
" Then third step\n");
Map<String, Result> stepsToResult = new HashMap<String, Result>();
stepsToResult.put("first step", result("passed"));
stepsToResult.put("second step", result("passed"));
stepsToResult.put("third step", result("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=\"1\" time=\"0.003\">\n" +
" <testcase classname=\"feature name\" name=\"scenario name\" time=\"0.003\">\n" +
" <system-out><![CDATA[" +
"Given first step............................................................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_pending_scenario() throws Throwable {
CucumberFeature feature = TestHelper.feature("path/test.feature",
"Feature: feature name\n" +
" Scenario: scenario name\n" +
" Given first step\n" +
" When second step\n" +
" Then third step\n");
Map<String, Result> stepsToResult = new HashMap<String, Result>();
stepsToResult.put("first step", result("pending"));
stepsToResult.put("second step", result("skipped"));
stepsToResult.put("third step", result("undefined"));
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=\"1\" tests=\"1\" time=\"0.001\">\n" +
" <testcase classname=\"feature name\" name=\"scenario name\" time=\"0.001\">\n" +
" <skipped><![CDATA[" +
"Given first step............................................................pending\n" +
"When second step............................................................skipped\n" +
"Then third step.............................................................undefined\n" +
"]]></skipped>\n" +
" </testcase>\n" +
"</testsuite>\n";
assertXmlEqual(expected, formatterOutput);
}
@Test
public void should_format_failed_scenario() throws Throwable {
CucumberFeature feature = TestHelper.feature("path/test.feature",
"Feature: feature name\n" +
" Scenario: scenario name\n" +
" Given first step\n" +
" When second step\n" +
" Then third step\n");
Map<String, Result> stepsToResult = new HashMap<String, Result>();
stepsToResult.put("first step", result("passed"));
stepsToResult.put("second step", result("passed"));
stepsToResult.put("third step", result("failed"));
long stepDuration = milliSeconds(1);
String formatterOutput = runFeatureWithJUnitFormatter(feature, stepsToResult, stepDuration);
String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<testsuite failures=\"1\" name=\"cucumber.runtime.formatter.JUnitFormatter\" skipped=\"0\" tests=\"1\" time=\"0.003\">\n" +
" <testcase classname=\"feature name\" name=\"scenario name\" time=\"0.003\">\n" +
" <failure message=\"the stack trace\"><![CDATA[" +
"Given first step............................................................passed\n" +
"When second step............................................................passed\n" +
"Then third step.............................................................failed\n" +
"\n" +
"StackTrace:\n" +
"the stack trace" +
"]]></failure>\n" +
" </testcase>\n" +
"</testsuite>\n";
assertXmlEqual(expected, formatterOutput);
}
@Test
public void should_handle_failure_in_before_hook() throws Throwable {
CucumberFeature feature = TestHelper.feature("path/test.feature",
"Feature: feature name\n" +
" Scenario: scenario name\n" +
" Given first step\n" +
" When second step\n" +
" Then third step\n");
Map<String, Result> stepsToResult = new HashMap<String, Result>();
stepsToResult.put("first step", result("passed"));
stepsToResult.put("second step", result("passed"));
stepsToResult.put("third step", result("passed"));
List<SimpleEntry<String, Result>> hooks = new ArrayList<SimpleEntry<String, Result>>();
hooks.add(TestHelper.hookEntry("before", result("failed")));
long stepHookDuration = milliSeconds(1);
String formatterOutput = runFeatureWithJUnitFormatter(feature, stepsToResult, hooks, stepHookDuration);
String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<testsuite failures=\"1\" name=\"cucumber.runtime.formatter.JUnitFormatter\" skipped=\"0\" tests=\"1\" time=\"0.001\">\n" +
" <testcase classname=\"feature name\" name=\"scenario name\" time=\"0.001\">\n" +
" <failure message=\"the stack trace\"><![CDATA[" +
"Given first step............................................................skipped\n" +
"When second step............................................................skipped\n" +
"Then third step.............................................................skipped\n" +
"\n" +
"StackTrace:\n" +
"the stack trace" +
"]]></failure>\n" +
" </testcase>\n" +
"</testsuite>\n";
assertXmlEqual(expected, formatterOutput);
}
@Test
public void should_handle_pending_in_before_hook() throws Throwable {
CucumberFeature feature = TestHelper.feature("path/test.feature",
"Feature: feature name\n" +
" Scenario: scenario name\n" +
" Given first step\n" +
" When second step\n" +
" Then third step\n");
Map<String, Result> stepsToResult = new HashMap<String, Result>();
stepsToResult.put("first step", result("skipped"));
stepsToResult.put("second step", result("skipped"));
stepsToResult.put("third step", result("skipped"));
List<SimpleEntry<String, Result>> hooks = new ArrayList<SimpleEntry<String, Result>>();
hooks.add(TestHelper.hookEntry("before", result("pending")));
long stepHookDuration = milliSeconds(1);
String formatterOutput = runFeatureWithJUnitFormatter(feature, stepsToResult, hooks, stepHookDuration);
String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<testsuite failures=\"0\" name=\"cucumber.runtime.formatter.JUnitFormatter\" skipped=\"1\" tests=\"1\" time=\"0.001\">\n" +
" <testcase classname=\"feature name\" name=\"scenario name\" time=\"0.001\">\n" +
" <skipped><![CDATA[" +
"Given first step............................................................skipped\n" +
"When second step............................................................skipped\n" +
"Then third step.............................................................skipped\n" +
"]]></skipped>\n" +
" </testcase>\n" +
"</testsuite>\n";
assertXmlEqual(expected, formatterOutput);
}
@Test
public void should_handle_failure_in_before_hook_with_background() throws Throwable {
CucumberFeature feature = TestHelper.feature("path/test.feature",
"Feature: feature name\n" +
" Background: background name\n" +
" Given first step\n" +
" Scenario: scenario name\n" +
" When second step\n" +
" Then third step\n");
Map<String, Result> stepsToResult = new HashMap<String, Result>();
stepsToResult.put("first step", result("passed"));
stepsToResult.put("second step", result("passed"));
stepsToResult.put("third step", result("passed"));
List<SimpleEntry<String, Result>> hooks = new ArrayList<SimpleEntry<String, Result>>();
hooks.add(TestHelper.hookEntry("before", result("failed")));
long stepHookDuration = milliSeconds(1);
String formatterOutput = runFeatureWithJUnitFormatter(feature, stepsToResult, hooks, stepHookDuration);
String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<testsuite failures=\"1\" name=\"cucumber.runtime.formatter.JUnitFormatter\" skipped=\"0\" tests=\"1\" time=\"0.001\">\n" +
" <testcase classname=\"feature name\" name=\"scenario name\" time=\"0.001\">\n" +
" <failure message=\"the stack trace\"><![CDATA[" +
"Given first step............................................................skipped\n" +
"When second step............................................................skipped\n" +
"Then third step.............................................................skipped\n" +
"\n" +
"StackTrace:\n" +
"the stack trace" +
"]]></failure>\n" +
" </testcase>\n" +
"</testsuite>\n";
assertXmlEqual(expected, formatterOutput);
}
@Test
public void should_handle_failure_in_after_hook() throws Throwable {
CucumberFeature feature = TestHelper.feature("path/test.feature",
"Feature: feature name\n" +
" Scenario: scenario name\n" +
" Given first step\n" +
" When second step\n" +
" Then third step\n");
Map<String, Result> stepsToResult = new HashMap<String, Result>();
stepsToResult.put("first step", result("passed"));
stepsToResult.put("second step", result("passed"));
stepsToResult.put("third step", result("passed"));
List<SimpleEntry<String, Result>> hooks = new ArrayList<SimpleEntry<String, Result>>();
hooks.add(TestHelper.hookEntry("after", result("failed")));
long stepHookDuration = milliSeconds(1);
String formatterOutput = runFeatureWithJUnitFormatter(feature, stepsToResult, hooks, stepHookDuration);
String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<testsuite failures=\"1\" name=\"cucumber.runtime.formatter.JUnitFormatter\" skipped=\"0\" tests=\"1\" time=\"0.004\">\n" +
" <testcase classname=\"feature name\" name=\"scenario name\" time=\"0.004\">\n" +
" <failure message=\"the stack trace\"><![CDATA[" +
"Given first step............................................................passed\n" +
"When second step............................................................passed\n" +
"Then third step.............................................................passed\n" +
"\n" +
"StackTrace:\n" +
"the stack trace" +
"]]></failure>\n" +
" </testcase>\n" +
"</testsuite>\n";
assertXmlEqual(expected, formatterOutput);
}
@Test
public void should_accumulate_time_from_steps_and_hooks() throws Throwable {
CucumberFeature feature = TestHelper.feature("path/test.feature",
"Feature: feature name\n" +
" Scenario: scenario name\n" +
" * first step\n" +
" * second step\n");
Map<String, Result> stepsToResult = new HashMap<String, Result>();
stepsToResult.put("first step", result("passed"));
stepsToResult.put("second step", result("passed"));
List<SimpleEntry<String, Result>> hooks = new ArrayList<SimpleEntry<String, Result>>();
hooks.add(TestHelper.hookEntry("before", result("passed")));
hooks.add(TestHelper.hookEntry("after", result("passed")));
long stepHookDuration = milliSeconds(1);
String formatterOutput = runFeatureWithJUnitFormatter(feature, stepsToResult, hooks, stepHookDuration);
String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<testsuite failures=\"0\" name=\"cucumber.runtime.formatter.JUnitFormatter\" skipped=\"0\" tests=\"1\" time=\"0.004\">\n" +
" <testcase classname=\"feature name\" name=\"scenario name\" time=\"0.004\">\n" +
" <system-out><![CDATA[" +
"* first step................................................................passed\n" +
"* second step...............................................................passed\n" +
"]]></system-out>\n" +
" </testcase>\n" +
"</testsuite>\n";
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, Result> stepsToResult = new HashMap<String, Result>();
stepsToResult.put("first step", result("passed"));
stepsToResult.put("second step", result("passed"));
stepsToResult.put("third step", result("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, Result> stepsToResult = new HashMap<String, Result>();
stepsToResult.put("first step", result("passed"));
stepsToResult.put("second step", result("passed"));
stepsToResult.put("third step", result("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, Result> stepsToResult = new HashMap<String, Result>();
stepsToResult.put("first step", result("passed"));
stepsToResult.put("second step", result("passed"));
stepsToResult.put("third step", result("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");
final JUnitFormatter junitFormatter = createJUnitFormatter(report);
junitFormatter.uri(uri());
junitFormatter.feature(feature("feature name"));
junitFormatter.scenario(scenario("scenario name"));
junitFormatter.step(step("keyword ", "step name"));
junitFormatter.step(step("keyword ", "step name"));
junitFormatter.match(match());
junitFormatter.result(result("passed"));
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=\"1\" name=\"cucumber.runtime.formatter.JUnitFormatter\" skipped=\"0\" time=\"0\">\n" +
" <testcase classname=\"feature name\" name=\"scenario name\" time=\"0\">\n" +
" <system-out><![CDATA[" +
"keyword step name...........................................................passed\n" +
"keyword step name...........................................................passed\n" +
"]]></system-out>\n" +
" </testcase>\n" +
"</testsuite>\n";
assertXmlEqual(expected, actual);
}
@Test
public void should_handle_one_step_at_the_time_execution() throws Exception {
final File report = File.createTempFile("cucumber-jvm-junit", ".xml");
final JUnitFormatter junitFormatter = createJUnitFormatter(report);
junitFormatter.uri(uri());
junitFormatter.feature(feature("feature name"));
junitFormatter.scenario(scenario("scenario name"));
junitFormatter.step(step("keyword ", "step name"));
junitFormatter.match(match());
junitFormatter.result(result("passed"));
junitFormatter.step(step("keyword ", "step name"));
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\" name=\"cucumber.runtime.formatter.JUnitFormatter\" skipped=\"0\" tests=\"1\" time=\"0\">\n" +
" <testcase classname=\"feature name\" name=\"scenario name\" time=\"0\">\n" +
" <system-out><![CDATA[" +
"keyword step name...........................................................passed\n" +
"keyword step name...........................................................passed\n" +
"]]></system-out>\n" +
" </testcase>\n" +
"</testsuite>\n";
assertXmlEqual(expected, actual);
}
@Test
public void should_handle_empty_scenarios() throws Throwable {
CucumberFeature feature = TestHelper.feature("path/test.feature",
"Feature: feature name\n" +
" Scenario: scenario name\n");
String formatterOutput = runFeatureWithJUnitFormatter(feature);
String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<testsuite failures=\"0\" name=\"cucumber.runtime.formatter.JUnitFormatter\" skipped=\"1\" tests=\"1\" time=\"0\">\n" +
" <testcase classname=\"feature name\" name=\"scenario name\" time=\"0\">\n" +
" <skipped message=\"The scenario has no steps\" />\n" +
" </testcase>\n" +
"</testsuite>\n";
assertXmlEqual(expected, formatterOutput);
}
@Test
public void should_add_dummy_testcase_if_no_scenarios_are_run_to_aviod_failed_jenkins_jobs() throws Throwable {
CucumberFeature feature = TestHelper.feature("path/test.feature",
"Feature: feature name\n");
String formatterOutput = runFeatureWithJUnitFormatter(feature);
String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<testsuite failures=\"0\" name=\"cucumber.runtime.formatter.JUnitFormatter\" skipped=\"0\" time=\"0\">\n" +
" <testcase classname=\"dummy\" name=\"dummy\">\n" +
" <skipped message=\"No features found\" />\n" +
" </testcase>\n" +
"</testsuite>\n";
assertXmlEqual(expected, formatterOutput);
}
private File runFeaturesWithJunitFormatter(final List<String> featurePaths) throws IOException {
return runFeaturesWithJunitFormatter(featurePaths, false);
}
private File runFeaturesWithJunitFormatter(final List<String> featurePaths, boolean strict) throws IOException {
File report = File.createTempFile("cucumber-jvm-junit", "xml");
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
final ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader(classLoader);
List<String> args = new ArrayList<String>();
if (strict) {
args.add("--strict");
}
args.add("--plugin");
args.add("junit:" + report.getAbsolutePath());
args.addAll(featurePaths);
RuntimeOptions runtimeOptions = new RuntimeOptions(args);
Backend backend = mock(Backend.class);
when(backend.getSnippet(any(Step.class), any(FunctionNameGenerator.class))).thenReturn("TEST SNIPPET");
final cucumber.runtime.Runtime runtime = new Runtime(resourceLoader, classLoader, asList(backend), runtimeOptions);
runtime.run();
return report;
}
private String runFeatureWithJUnitFormatter(final CucumberFeature feature) throws Throwable {
return runFeatureWithJUnitFormatter(feature, new HashMap<String, Result>(), 0L);
}
private String runFeatureWithJUnitFormatter(final CucumberFeature feature, final Map<String, Result> stepsToResult, final long stepHookDuration)
throws Throwable {
return runFeatureWithJUnitFormatter(feature, stepsToResult, Collections.<SimpleEntry<String, Result>>emptyList(), stepHookDuration);
}
private String runFeatureWithJUnitFormatter(final CucumberFeature feature, final Map<String, Result> stepsToResult,
final List<SimpleEntry<String, Result>> hooks, final long stepHookDuration) throws Throwable {
final File report = File.createTempFile("cucumber-jvm-junit", ".xml");
final JUnitFormatter junitFormatter = createJUnitFormatter(report);
TestHelper.runFeatureWithFormatter(feature, stepsToResult, hooks, stepHookDuration, junitFormatter, junitFormatter);
return new Scanner(new FileInputStream(report), "UTF-8").useDelimiter("\\A").next();
}
private void assertXmlEqual(String expectedPath, File actual) throws IOException, ParserConfigurationException, SAXException {
XMLUnit.setIgnoreWhitespace(true);
InputStreamReader control = new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream(expectedPath), "UTF-8");
Diff diff = new Diff(control, new FileReader(actual));
assertTrue("XML files are similar " + diff, diff.identical());
}
private void assertXmlEqual(String expected, String actual) throws SAXException, IOException {
XMLUnit.setIgnoreWhitespace(true);
Diff diff = new Diff(expected, actual);
assertTrue("XML files are similar " + diff + "\nFormatterOutput = " + actual, diff.identical());
}
private JUnitFormatter createJUnitFormatter(final File report) throws IOException {
return new JUnitFormatter(Utils.toURL(report.getAbsolutePath()));
}
private String uri() {
return "uri";
}
private Feature feature(String featureName) {
Feature feature = mock(Feature.class);
when(feature.getName()).thenReturn(featureName);
return feature;
}
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;
}
private Step step(String keyword, String stepName) {
Step step = mock(Step.class);
when(step.getKeyword()).thenReturn(keyword);
when(step.getName()).thenReturn(stepName);
return step;
}
private Match match() {
return mock(Match.class);
}
private Long milliSeconds(int milliSeconds) {
return milliSeconds * 1000000L;
}
}