diff --git a/android/src/main/java/cucumber/runtime/android/AndroidInstrumentationReporter.java b/android/src/main/java/cucumber/runtime/android/AndroidInstrumentationReporter.java index 312c9c5845..e48b6b0ef0 100644 --- a/android/src/main/java/cucumber/runtime/android/AndroidInstrumentationReporter.java +++ b/android/src/main/java/cucumber/runtime/android/AndroidInstrumentationReporter.java @@ -8,9 +8,11 @@ import cucumber.api.event.EventPublisher; import cucumber.api.event.TestCaseFinished; import cucumber.api.event.TestCaseStarted; +import cucumber.api.event.TestSourceRead; import cucumber.api.event.TestStepFinished; import cucumber.api.formatter.Formatter; import cucumber.runtime.Runtime; +import cucumber.runtime.formatter.TestSourcesModel; import java.io.PrintWriter; import java.io.StringWriter; @@ -56,6 +58,11 @@ public static class StatusCodes { public static final int OK = 0; } + /** + * The collected TestSourceRead events. + */ + private final TestSourcesModel testSources = new TestSourcesModel(); + /** * The current cucumber runtime. */ @@ -69,7 +76,7 @@ public static class StatusCodes { /** * The total number of tests which will be executed. */ - private final int numberOfTests; + private int numberOfTests; /** * The severest step result of the current test execution. @@ -78,15 +85,30 @@ public static class StatusCodes { private Result severestResult; /** - * The location in the feature file of the current test case. + * The uri of the feature file of the current test case. + */ + private String currentUri; + + /** + * The name of the current feature. */ - private String currentPath; + private String currentFeatureName; /** * The name of the current test case. */ private String currentTestCaseName; + /** + * The event handler for the {@link TestSourceRead} events. + */ + private final EventHandler testSourceReadHandler = new EventHandler() { + @Override + public void receive(TestSourceRead event) { + testSourceRead(event); + } + }; + /** * The event handler for the {@link TestCaseStarted} events. */ @@ -126,26 +148,36 @@ public void receive(TestCaseFinished event) { */ public AndroidInstrumentationReporter( final Runtime runtime, - final Instrumentation instrumentation, - final int numberOfTests) { + final Instrumentation instrumentation) { this.runtime = runtime; this.instrumentation = instrumentation; - this.numberOfTests = numberOfTests; } @Override public void setEventPublisher(final EventPublisher publisher) { + publisher.registerHandlerFor(TestSourceRead.class, testSourceReadHandler); publisher.registerHandlerFor(TestCaseStarted.class, testCaseStartedHandler); publisher.registerHandlerFor(TestCaseFinished.class, testCaseFinishedHandler); publisher.registerHandlerFor(TestStepFinished.class, testStepFinishedHandler); } + public void setNumberOfTests(final int numberOfTests) { + this.numberOfTests = numberOfTests; + } + + void testSourceRead(final TestSourceRead event) { + testSources.addTestSourceReadEvent(event.path, event); + } + void startTestCase(final TestCase testCase) { - currentPath = testCase.getPath(); + if (!testCase.getPath().equals(currentUri)) { + currentUri = testCase.getPath(); + currentFeatureName = testSources.getFeatureName(currentUri); + } currentTestCaseName = testCase.getName(); resetSeverestResult(); - final Bundle testStart = createBundle(currentPath, currentTestCaseName); + final Bundle testStart = createBundle(currentFeatureName, currentTestCaseName); instrumentation.sendStatus(StatusCodes.START, testStart); } @@ -154,7 +186,7 @@ void finishTestStep(final Result result) { } void finishTestCase() { - final Bundle testResult = createBundle(currentPath, currentTestCaseName); + final Bundle testResult = createBundle(currentFeatureName, currentTestCaseName); switch (severestResult.getStatus()) { case FAILED: diff --git a/android/src/main/java/cucumber/runtime/android/CucumberExecutor.java b/android/src/main/java/cucumber/runtime/android/CucumberExecutor.java index c46131e5f7..b068636371 100644 --- a/android/src/main/java/cucumber/runtime/android/CucumberExecutor.java +++ b/android/src/main/java/cucumber/runtime/android/CucumberExecutor.java @@ -89,8 +89,13 @@ public CucumberExecutor(final Arguments arguments, final Instrumentation instrum ResourceLoader resourceLoader = new AndroidResourceLoader(context); this.runtime = new Runtime(resourceLoader, classLoader, createBackends(), runtimeOptions); + AndroidInstrumentationReporter instrumentationReporter = new AndroidInstrumentationReporter(runtime, instrumentation); + runtimeOptions.addPlugin(instrumentationReporter); + runtimeOptions.addPlugin(new AndroidLogcatReporter(runtime, TAG)); + List cucumberFeatures = runtimeOptions.cucumberFeatures(resourceLoader, runtime.getEventBus()); this.pickleEvents = FeatureCompiler.compile(cucumberFeatures, this.runtime); + instrumentationReporter.setNumberOfTests(getNumberOfConcreteScenarios()); } /** @@ -98,9 +103,6 @@ public CucumberExecutor(final Arguments arguments, final Instrumentation instrum */ public void execute() { - runtimeOptions.addPlugin(new AndroidInstrumentationReporter(runtime, instrumentation, getNumberOfConcreteScenarios())); - runtimeOptions.addPlugin(new AndroidLogcatReporter(runtime, TAG)); - // TODO: This is duplicated in info.cucumber.Runtime. final StepDefinitionReporter stepDefinitionReporter = runtimeOptions.stepDefinitionReporter(classLoader); diff --git a/android/src/test/java/cucumber/runtime/android/AndroidInstrumentationReporterTest.java b/android/src/test/java/cucumber/runtime/android/AndroidInstrumentationReporterTest.java index 3dc628dc59..6cf9cfd971 100644 --- a/android/src/test/java/cucumber/runtime/android/AndroidInstrumentationReporterTest.java +++ b/android/src/test/java/cucumber/runtime/android/AndroidInstrumentationReporterTest.java @@ -2,6 +2,7 @@ import android.app.Instrumentation; import android.os.Bundle; +import cucumber.api.event.TestSourceRead; import cucumber.api.PendingException; import cucumber.api.Result; import cucumber.api.TestCase; @@ -36,6 +37,11 @@ public class AndroidInstrumentationReporterTest { private final Runtime runtime = mock(Runtime.class); private final Instrumentation instrumentation = mock(Instrumentation.class); + private final TestSourceRead testSourceRead = new TestSourceRead( + 0l, + "path/file.feature", + "en", + "Feature: feature name\n Scenario: some important scenario\n"); private final TestCase testCase = mock(TestCase.class); private final Result firstResult = mock(Result.class); private final Result secondResult = mock(Result.class); @@ -51,9 +57,11 @@ public void beforeEachTest() { public void feature_name_and_keyword_is_contained_in_start_signal() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 1); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); // when + formatter.testSourceRead(testSourceRead); + formatter.setNumberOfTests(1); formatter.startTestCase(testCase); // then @@ -63,17 +71,19 @@ public void feature_name_and_keyword_is_contained_in_start_signal() { final Bundle actualBundle = captor.getValue(); - assertThat(actualBundle.getString(AndroidInstrumentationReporter.StatusKeys.CLASS), containsString(testCase.getPath())); + assertThat(actualBundle.getString(AndroidInstrumentationReporter.StatusKeys.CLASS), containsString("feature name")); } @Test public void feature_name_and_keyword_is_contained_in_end_signal() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 1); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.PASSED); // when + formatter.testSourceRead(testSourceRead); + formatter.setNumberOfTests(1); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestCase(); @@ -85,16 +95,17 @@ public void feature_name_and_keyword_is_contained_in_end_signal() { final Bundle actualBundle = captor.getValue(); - assertThat(actualBundle.getString(AndroidInstrumentationReporter.StatusKeys.CLASS), containsString(testCase.getPath())); + assertThat(actualBundle.getString(AndroidInstrumentationReporter.StatusKeys.CLASS), containsString("feature name")); } @Test public void scenario_name_is_contained_in_start_signal() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 1); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); // when + formatter.setNumberOfTests(1); formatter.startTestCase(testCase); // then @@ -111,10 +122,11 @@ public void scenario_name_is_contained_in_start_signal() { public void scenario_name_is_contained_in_end_signal() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 1); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.PASSED); // when + formatter.setNumberOfTests(1); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestCase(); @@ -133,11 +145,12 @@ public void scenario_name_is_contained_in_end_signal() { public void any_step_exception_causes_test_error() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 1); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.FAILED); when(firstResult.getError()).thenReturn(new RuntimeException("some random runtime exception")); // when + formatter.setNumberOfTests(1); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestCase(); @@ -155,12 +168,13 @@ public void any_step_exception_causes_test_error() { public void any_failing_step_causes_test_failure() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 1); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.FAILED); when(firstResult.getError()).thenReturn(new AssertionError("some test assertion went wrong")); when(firstResult.getErrorMessage()).thenReturn("some test assertion went wrong"); // when + formatter.setNumberOfTests(1); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestCase(); @@ -177,11 +191,12 @@ public void any_failing_step_causes_test_failure() { public void any_undefined_step_causes_test_error() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 1); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.UNDEFINED); when(runtime.getSnippets()).thenReturn(Collections.singletonList("some snippet")); // when + formatter.setNumberOfTests(1); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestCase(); @@ -198,10 +213,11 @@ public void any_undefined_step_causes_test_error() { public void passing_step_causes_test_success() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 1); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.PASSED); // when + formatter.setNumberOfTests(1); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestCase(); @@ -214,11 +230,12 @@ public void passing_step_causes_test_success() { public void skipped_step_causes_test_success() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 2); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.PASSED); mockResultStatus(secondResult, Result.Type.SKIPPED); // when + formatter.setNumberOfTests(2); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestStep(secondResult); @@ -233,7 +250,7 @@ public void skipped_step_causes_test_success() { public void first_step_result_exception_is_reported() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 2); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.FAILED); when(firstResult.getError()).thenReturn(new RuntimeException("first exception")); @@ -241,6 +258,7 @@ public void first_step_result_exception_is_reported() { when(secondResult.getError()).thenReturn(new RuntimeException("second exception")); // when + formatter.setNumberOfTests(2); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestStep(secondResult); @@ -258,13 +276,14 @@ public void first_step_result_exception_is_reported() { public void undefined_step_overrides_preceding_passed_step() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 2); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.PASSED); mockResultStatus(secondResult, Result.Type.UNDEFINED); when(runtime.getSnippets()).thenReturn(Collections.singletonList("some snippet")); // when + formatter.setNumberOfTests(2); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestStep(secondResult); @@ -282,7 +301,7 @@ public void undefined_step_overrides_preceding_passed_step() { public void pending_step_overrides_preceding_passed_step() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 2); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.PASSED); mockResultStatus(secondResult, Result.Type.PENDING); @@ -290,6 +309,7 @@ public void pending_step_overrides_preceding_passed_step() { when(secondResult.getErrorMessage()).thenReturn("step is pending"); // when + formatter.setNumberOfTests(2); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestStep(secondResult); @@ -307,7 +327,7 @@ public void pending_step_overrides_preceding_passed_step() { public void failed_step_overrides_preceding_passed_step() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 2); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.PASSED); mockResultStatus(secondResult, Result.Type.FAILED); @@ -315,6 +335,7 @@ public void failed_step_overrides_preceding_passed_step() { when(secondResult.getErrorMessage()).thenReturn("some assertion went wrong"); // when + formatter.setNumberOfTests(2); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestStep(secondResult); @@ -332,13 +353,14 @@ public void failed_step_overrides_preceding_passed_step() { public void error_step_overrides_preceding_passed_step() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 2); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.PASSED); mockResultStatus(secondResult, Result.Type.FAILED); when(secondResult.getError()).thenReturn(new RuntimeException("some exception")); // when + formatter.setNumberOfTests(2); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestStep(secondResult); @@ -356,7 +378,7 @@ public void error_step_overrides_preceding_passed_step() { public void failed_step_does_not_overrides_preceding_undefined_step() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 2); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.UNDEFINED); when(runtime.getSnippets()).thenReturn(Collections.singletonList("some snippet")); @@ -365,6 +387,7 @@ public void failed_step_does_not_overrides_preceding_undefined_step() { when(secondResult.getErrorMessage()).thenReturn("some assertion went wrong"); // when + formatter.setNumberOfTests(2); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestStep(secondResult); @@ -382,7 +405,7 @@ public void failed_step_does_not_overrides_preceding_undefined_step() { public void error_step_does_not_override_preceding_failed_step() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 2); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.FAILED); when(firstResult.getError()).thenReturn(new AssertionError("some assertion went wrong")); when(firstResult.getErrorMessage()).thenReturn("some assertion went wrong"); @@ -391,6 +414,7 @@ public void error_step_does_not_override_preceding_failed_step() { when(secondResult.getError()).thenReturn(new RuntimeException("some exception")); // when + formatter.setNumberOfTests(2); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestStep(secondResult); @@ -407,7 +431,7 @@ public void error_step_does_not_override_preceding_failed_step() { @Test public void step_result_contains_only_the_current_scenarios_severest_result() { // given - final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation, 2); + final AndroidInstrumentationReporter formatter = new AndroidInstrumentationReporter(runtime, instrumentation); mockResultStatus(firstResult, Result.Type.FAILED); when(firstResult.getError()).thenReturn(new AssertionError("some assertion went wrong")); when(firstResult.getErrorMessage()).thenReturn("some assertion went wrong"); @@ -415,6 +439,7 @@ public void step_result_contains_only_the_current_scenarios_severest_result() { mockResultStatus(secondResult, Result.Type.PASSED); // when + formatter.setNumberOfTests(2); formatter.startTestCase(testCase); formatter.finishTestStep(firstResult); formatter.finishTestCase(); diff --git a/core/src/main/java/cucumber/runtime/formatter/HTMLFormatter.java b/core/src/main/java/cucumber/runtime/formatter/HTMLFormatter.java index be5fa839d2..1a010f0d84 100644 --- a/core/src/main/java/cucumber/runtime/formatter/HTMLFormatter.java +++ b/core/src/main/java/cucumber/runtime/formatter/HTMLFormatter.java @@ -139,7 +139,7 @@ public void setEventPublisher(EventPublisher publisher) { } private void handleTestSourceRead(TestSourceRead event) { - testSources.addSource(event.path, event.source); + testSources.addTestSourceReadEvent(event.path, event); } private void handleTestCaseStarted(TestCaseStarted event) { diff --git a/core/src/main/java/cucumber/runtime/formatter/JSONFormatter.java b/core/src/main/java/cucumber/runtime/formatter/JSONFormatter.java index 8176f3a508..4d2c43c81a 100644 --- a/core/src/main/java/cucumber/runtime/formatter/JSONFormatter.java +++ b/core/src/main/java/cucumber/runtime/formatter/JSONFormatter.java @@ -105,7 +105,7 @@ public void setEventPublisher(EventPublisher publisher) { } private void handleTestSourceRead(TestSourceRead event) { - testSources.addSource(event.path, event.source); + testSources.addTestSourceReadEvent(event.path, event); } private void handleTestCaseStarted(TestCaseStarted event) { diff --git a/core/src/main/java/cucumber/runtime/formatter/JUnitFormatter.java b/core/src/main/java/cucumber/runtime/formatter/JUnitFormatter.java index c739555f71..99faed68f0 100644 --- a/core/src/main/java/cucumber/runtime/formatter/JUnitFormatter.java +++ b/core/src/main/java/cucumber/runtime/formatter/JUnitFormatter.java @@ -36,10 +36,8 @@ import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map; class JUnitFormatter implements Formatter, StrictAware { private final Writer out; @@ -105,7 +103,7 @@ public void setEventPublisher(EventPublisher publisher) { } private void handleTestSourceRead(TestSourceRead event) { - TestCase.sourceMap.put(event.path, event); + TestCase.testSources.addTestSourceReadEvent(event.path, event); } private void handleTestCaseStarted(TestCaseStarted event) { @@ -201,7 +199,7 @@ public void setStrict(boolean strict) { private static class TestCase { private static final DecimalFormat NUMBER_FORMAT = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US); - private static final Map sourceMap = new HashMap(); + private static final TestSourcesModel testSources = new TestSourcesModel(); static { NUMBER_FORMAT.applyPattern("0.######"); @@ -224,7 +222,7 @@ private Element createElement(Document doc) { } private void writeElement(Document doc, Element tc) { - tc.setAttribute("classname", testCase.getPath()); + tc.setAttribute("classname", testSources.getFeatureName(currentFeatureFile)); tc.setAttribute("name", calculateElementName(testCase)); } @@ -299,7 +297,7 @@ private void addStepAndResultListing(StringBuilder sb) { } private String getKeywordFromSource(int stepLine) { - TestSourceRead event = sourceMap.get(currentFeatureFile); + TestSourceRead event = testSources.getTestSourceReadEvent(currentFeatureFile); String trimmedSourceLine = event.source.split("\n")[stepLine - 1].trim(); GherkinDialect dialect = new GherkinDialectProvider(event.language).getDefaultDialect(); for (String keyword : dialect.getStepKeywords()) { diff --git a/core/src/main/java/cucumber/runtime/formatter/PrettyFormatter.java b/core/src/main/java/cucumber/runtime/formatter/PrettyFormatter.java index b7528a55ad..f30d22889f 100644 --- a/core/src/main/java/cucumber/runtime/formatter/PrettyFormatter.java +++ b/core/src/main/java/cucumber/runtime/formatter/PrettyFormatter.java @@ -115,7 +115,7 @@ public void setMonochrome(boolean monochrome) { } private void handleTestSourceRead(TestSourceRead event) { - testSources.addSource(event.path, event.source); + testSources.addTestSourceReadEvent(event.path, event); } private void handleTestCaseStarted(TestCaseStarted event) { diff --git a/core/src/main/java/cucumber/runtime/formatter/TestSourcesModel.java b/core/src/main/java/cucumber/runtime/formatter/TestSourcesModel.java index 30893fed62..e24057bfbb 100644 --- a/core/src/main/java/cucumber/runtime/formatter/TestSourcesModel.java +++ b/core/src/main/java/cucumber/runtime/formatter/TestSourcesModel.java @@ -1,6 +1,9 @@ package cucumber.runtime.formatter; +import cucumber.api.event.TestSourceRead; import gherkin.AstBuilder; +import gherkin.GherkinDialect; +import gherkin.GherkinDialectProvider; import gherkin.Parser; import gherkin.ParserException; import gherkin.TokenMatcher; @@ -18,7 +21,7 @@ import java.util.Map; public class TestSourcesModel { - private final Map pathToSourceMap = new HashMap(); + private final Map pathToReadEventMap = new HashMap(); private final Map pathToAstMap = new HashMap(); private final Map> pathToNodeMap = new HashMap>(); @@ -75,8 +78,8 @@ public static String convertToId(String name) { return name.replaceAll("[\\s'_,!]", "-").toLowerCase(); } - public void addSource(String path, String source) { - pathToSourceMap.put(path, source); + public void addTestSourceReadEvent(String path, TestSourceRead event) { + pathToReadEventMap.put(path, event); } public Feature getFeature(String path) { @@ -114,14 +117,46 @@ public boolean hasBackground(String path, int line) { return false; } + public TestSourceRead getTestSourceReadEvent(String uri) { + if (pathToReadEventMap.containsKey(uri)) { + return pathToReadEventMap.get(uri); + } + return null; + } + + public String getFeatureName(String uri) { + if (pathToReadEventMap.containsKey(uri)) { + TestSourceRead event = pathToReadEventMap.get(uri); + String featureLine = getFeatureLine(event.source); + if (featureLine != null) { + GherkinDialect dialect = new GherkinDialectProvider(event.language).getDefaultDialect(); + for (String keyword : dialect.getFeatureKeywords()) { + if (featureLine.trim().startsWith(keyword)) { + return featureLine.substring(featureLine.indexOf(":") + 1).trim(); + } + } + } + } + return ""; + } + + private String getFeatureLine(String source) { + for (String line : source.split("\n")) { + if (line.contains(":") && !line.contains("#")) { + return line; + } + } + return null; + } + private void parseGherkinSource(String path) { - if (!pathToSourceMap.containsKey(path)) { + if (!pathToReadEventMap.containsKey(path)) { return; } Parser parser = new Parser(new AstBuilder()); TokenMatcher matcher = new TokenMatcher(); try { - GherkinDocument gherkinDocument = parser.parse(pathToSourceMap.get(path), matcher); + GherkinDocument gherkinDocument = parser.parse(pathToReadEventMap.get(path).source, matcher); pathToAstMap.put(path, gherkinDocument); Map nodeMap = new HashMap(); AstNode currentParent = new AstNode(gherkinDocument.getFeature(), null); diff --git a/core/src/test/java/cucumber/runtime/formatter/JUnitFormatterTest.java b/core/src/test/java/cucumber/runtime/formatter/JUnitFormatterTest.java index 28c076f19b..9819e9e740 100644 --- a/core/src/test/java/cucumber/runtime/formatter/JUnitFormatterTest.java +++ b/core/src/test/java/cucumber/runtime/formatter/JUnitFormatterTest.java @@ -87,7 +87,7 @@ public void should_format_passed_scenario() throws Throwable { String expected = "\n" + "\n" + - " \n" + + " \n" + " \n" + "\n" + - " \n" + + " \n" + " \n" + "\n" + - " \n" + + " \n" + " \n" + "\n" + - " \n" + + " \n" + " \n" + "\n" + - " \n" + + " \n" + " \n" + "\n" + - " \n" + + " \n" + " \n" + "\n" + - " \n" + + " \n" + " \n" + "\n" + - " \n" + + " \n" + " \n" + "\n" + - " \n" + + " \n" + " \n" + "\n" + - " \n" + + " \n" + " \n" + " \n" + - " \n" + + " \n" + " \n" + "\n" + - " \n" + + " \n" + " \n" + " \n" + - " \n" + + " \n" + " \n" + " \n" + - " \n" + + " \n" + " \n" + " \n" + - " \n" + + " \n" + " \n" + "\n" + - " \n" + + " \n" + " \n" + " \n" + - " \n" + + " \n" + " - + - + - + - + - + - + - + - + - + - +