diff --git a/plugins/cucumber-jvm-formatter/cucumber-jvm-formatter.iml b/plugins/cucumber-jvm-formatter/cucumber-jvm-formatter.iml
index 349de40e6270..fd438454136e 100644
--- a/plugins/cucumber-jvm-formatter/cucumber-jvm-formatter.iml
+++ b/plugins/cucumber-jvm-formatter/cucumber-jvm-formatter.iml
@@ -8,5 +8,6 @@
+
\ No newline at end of file
diff --git a/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvm2SMFormatter.java b/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvm2SMFormatter.java
new file mode 100644
index 000000000000..ca3980e24e8a
--- /dev/null
+++ b/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvm2SMFormatter.java
@@ -0,0 +1,215 @@
+package org.jetbrains.plugins.cucumber.java.run;
+
+import cucumber.api.TestCase;
+import cucumber.api.TestStep;
+import cucumber.api.event.*;
+import cucumber.api.formatter.Formatter;
+import gherkin.events.PickleEvent;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+import static cucumber.api.Result.Type.*;
+import static org.jetbrains.plugins.cucumber.java.run.CucumberJvmSMFormatterUtil.*;
+
+@SuppressWarnings("unused")
+public class CucumberJvm2SMFormatter implements Formatter {
+ private static final String EXAMPLES_CAPTION = "Examples:";
+ private static final String SCENARIO_OUTLINE_CAPTION = "Scenario: Line: ";
+ private Map pathToDescription = new HashMap();
+ private String currentFilePath;
+ private int currentScenarioOutlineLine;
+ private String currentScenarioOutlineName;
+
+ public CucumberJvm2SMFormatter() {
+ outCommand(String.format(TEMPLATE_ENTER_THE_MATRIX, getCurrentTime()));
+ outCommand(String.format(TEMPLATE_SCENARIO_COUNTING_STARTED, 0, getCurrentTime()));
+ }
+
+ private EventHandler testCaseStartedHandler = new EventHandler() {
+ public void receive(TestCaseStarted event) {
+ CucumberJvm2SMFormatter.this.handleTestCaseStarted(event);
+ }
+ };
+
+ private EventHandler testCaseFinishedHandler = new EventHandler() {
+ public void receive(TestCaseFinished event) {
+ handleTestCaseFinished(event);
+ }
+ };
+
+ private EventHandler testRunFinishedHandler = new EventHandler() {
+ public void receive(TestRunFinished event) {
+ CucumberJvm2SMFormatter.this.handleTestRunFinished(event);
+ }
+ };
+
+ private EventHandler testStepStartedHandler = new EventHandler() {
+ public void receive(TestStepStarted event) {
+ handleTestStepStarted(event);
+ }
+ };
+
+ private EventHandler testStepFinishedHandler = new EventHandler() {
+ public void receive(TestStepFinished event) {
+ handleTestStepFinished(event);
+ }
+ };
+
+ private EventHandler testSourceReadHandler = new EventHandler() {
+ public void receive(TestSourceRead event) {
+ CucumberJvm2SMFormatter.this.handleTestSourceRead(event);
+ }
+ };
+
+ @Override
+ public void setEventPublisher(EventPublisher publisher) {
+ publisher.registerHandlerFor(TestCaseStarted.class, this.testCaseStartedHandler);
+ publisher.registerHandlerFor(TestCaseFinished.class, this.testCaseFinishedHandler);
+
+ publisher.registerHandlerFor(TestStepStarted.class, this.testStepStartedHandler);
+ publisher.registerHandlerFor(TestStepFinished.class, this.testStepFinishedHandler);
+ publisher.registerHandlerFor(TestSourceRead.class, this.testSourceReadHandler);
+
+ publisher.registerHandlerFor(TestRunFinished.class, this.testRunFinishedHandler);
+ }
+
+ private void handleTestCaseStarted(TestCaseStarted event) {
+ if (currentFilePath == null) {
+ outCommand(String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(), event.testCase.getUri(),
+ getFeatureFileDescription(event.testCase.getUri())));
+ }
+ else if (!event.testCase.getUri().equals(currentFilePath)) {
+ closeCurrentScenarioOutline();
+ outCommand(String.format(TEMPLATE_TEST_SUITE_FINISHED, getCurrentTime(),
+ getFeatureFileDescription(currentFilePath)));
+ outCommand(String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(), event.testCase.getUri(),
+ getFeatureFileDescription(event.testCase.getUri())));
+ }
+
+ if (isScenarioOutline(event.testCase)) {
+ int mainScenarioLine = getScenarioOutlineLine(event.testCase);
+ if (currentScenarioOutlineLine != mainScenarioLine || currentFilePath == null ||
+ !currentFilePath.equals(event.testCase.getUri())) {
+ closeCurrentScenarioOutline();
+ currentScenarioOutlineLine = mainScenarioLine;
+ currentScenarioOutlineName = event.testCase.getName();
+ outCommand(String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(),
+ event.testCase.getUri() + ":" + currentScenarioOutlineLine, currentScenarioOutlineName));
+ outCommand(String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(), "", EXAMPLES_CAPTION));
+ }
+ } else {
+ closeCurrentScenarioOutline();
+ }
+ currentFilePath = event.testCase.getUri();
+
+ outCommand(String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(),
+ event.testCase.getUri() + ":" + event.testCase.getLine(), getScenarioName(event.testCase)));
+ }
+
+ private static void handleTestCaseFinished(TestCaseFinished event) {
+ outCommand(String.format(TEMPLATE_TEST_SUITE_FINISHED, getCurrentTime(), getScenarioName(event.testCase)));
+ }
+
+ private void handleTestRunFinished(TestRunFinished event) {
+ closeCurrentScenarioOutline();
+ outCommand(String.format(TEMPLATE_TEST_SUITE_FINISHED, getCurrentTime(),
+ getFeatureFileDescription(currentFilePath)));
+ }
+ private static void handleTestStepStarted(TestStepStarted event) {
+ if (event.testStep.isHook()) {
+ return;
+ }
+
+ outCommand(String.format(TEMPLATE_TEST_STARTED, getCurrentTime(), getStepLocation(event.testStep),
+ getStepName(event.testStep)));
+ }
+
+ private static void handleTestStepFinished(TestStepFinished event) {
+ if (event.testStep.isHook()) {
+ return;
+ }
+ if (event.result.getStatus() == PASSED) {
+ // write nothing
+ } else if (event.result.getStatus() == SKIPPED || event.result.getStatus() == PENDING) {
+ outCommand(String.format(TEMPLATE_TEST_PENDING, getStepName(event.testStep), getCurrentTime()));
+ } else {
+ outCommand(String.format(TEMPLATE_TEST_FAILED, getCurrentTime(), "",
+ escape(event.result.getErrorMessage()), getStepName(event.testStep), ""));
+ }
+ Long duration = event.result.getDuration() != null ? event.result.getDuration() / 1000000: 0;
+ outCommand(String.format(TEMPLATE_TEST_FINISHED, getCurrentTime(), duration, getStepName(event.testStep)));
+ }
+
+ private String getFeatureFileDescription(String uri) {
+ if (pathToDescription.containsKey(uri)) {
+ return pathToDescription.get(uri);
+ }
+ return uri;
+ }
+
+ private void handleTestSourceRead(TestSourceRead event) {
+ closeCurrentScenarioOutline();
+
+ String[] lines = event.source.split("\n");
+ if (lines.length > 0) {
+ pathToDescription.put(event.uri, lines[0]);
+ } else {
+ pathToDescription.put(event.uri, event.source);
+ }
+ }
+
+ private void closeCurrentScenarioOutline() {
+ if (currentScenarioOutlineLine > 0) {
+ outCommand(String.format(TEMPLATE_TEST_SUITE_FINISHED, getCurrentTime(), EXAMPLES_CAPTION));
+ outCommand(String.format(TEMPLATE_TEST_SUITE_FINISHED, getCurrentTime(), currentScenarioOutlineName));
+ currentScenarioOutlineLine = 0;
+ currentScenarioOutlineName = null;
+ }
+ }
+
+ private static String getStepLocation(TestStep step) {
+ return step.getStepLocation() + ":" + step.getStepLine();
+ }
+
+ private static String getStepName(TestStep step) {
+ return step.getStepText();
+ }
+
+ private static void outCommand(String s) {
+ //noinspection UseOfSystemOutOrSystemErr
+ System.out.println(s);
+ }
+
+ private static PickleEvent getPickleEvent(TestCase testCase) {
+ try {
+ Field pickleEventField = TestCase.class.getDeclaredField("pickleEvent");
+ pickleEventField.setAccessible(true);
+ return (PickleEvent)pickleEventField.get(testCase);
+ }
+ catch (Exception ignored) {
+ }
+ return null;
+ }
+
+ private static boolean isScenarioOutline(TestCase testCase) {
+ PickleEvent pickleEvent = getPickleEvent(testCase);
+ return pickleEvent != null && pickleEvent.pickle.getLocations().size() > 1;
+ }
+
+ private static int getScenarioOutlineLine(TestCase testCase) {
+ PickleEvent pickleEvent = getPickleEvent(testCase);
+ if (pickleEvent != null) {
+ return pickleEvent.pickle.getLocations().get(pickleEvent.pickle.getLocations().size() - 1).getLine();
+ }
+ return 0;
+ }
+
+ private static String getScenarioName(TestCase testCase) {
+ if (isScenarioOutline(testCase)) {
+ return SCENARIO_OUTLINE_CAPTION + testCase.getLine();
+ }
+ return testCase.getName();
+ }
+}
diff --git a/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatter.java b/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatter.java
index 46c4220049e6..d7234b755c6e 100644
--- a/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatter.java
+++ b/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatter.java
@@ -7,14 +7,13 @@ import gherkin.formatter.model.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.text.SimpleDateFormat;
import java.util.ArrayDeque;
-import java.util.Date;
import java.util.List;
import java.util.Queue;
+import static org.jetbrains.plugins.cucumber.java.run.CucumberJvmSMFormatterUtil.*;
+
public class CucumberJvmSMFormatter implements Formatter, Reporter {
- public static final String TEAMCITY_PREFIX = "##teamcity";
public static final int MILLION = 1000000;
private int scenarioCount;
private int passedScenarioCount;
@@ -28,33 +27,6 @@ public class CucumberJvmSMFormatter implements Formatter, Reporter {
private int undefinedStepCount;
private boolean endedByNewLine = true;
- private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSZ");
-
- private static final String TEMPLATE_TEST_STARTED =
- TEAMCITY_PREFIX + "[testStarted timestamp = '%s' locationHint = 'file:///%s' captureStandardOutput = 'true' name = '%s']";
- private static final String TEMPLATE_TEST_FAILED =
- TEAMCITY_PREFIX + "[testFailed timestamp = '%s' details = '%s' message = '%s' name = '%s' %s]";
- private static final String TEMPLATE_SCENARIO_FAILED = TEAMCITY_PREFIX + "[customProgressStatus timestamp='%s' type='testFailed']";
- private static final String TEMPLATE_TEST_PENDING =
- TEAMCITY_PREFIX + "[testIgnored name = '%s' message = 'Skipped step' timestamp = '%s']";
-
- private static final String TEMPLATE_TEST_FINISHED =
- TEAMCITY_PREFIX +
- "[testFinished timestamp = '%s' duration = '%s' name = '%s']";
-
- private static final String TEMPLATE_ENTER_THE_MATRIX = TEAMCITY_PREFIX + "[enteredTheMatrix timestamp = '%s']";
-
- private static final String TEMPLATE_TEST_SUITE_STARTED =
- TEAMCITY_PREFIX + "[testSuiteStarted timestamp = '%s' locationHint = 'file://%s' name = '%s']";
- private static final String TEMPLATE_TEST_SUITE_FINISHED = TEAMCITY_PREFIX + "[testSuiteFinished timestamp = '%s' name = '%s']";
-
- private static final String TEMPLATE_SCENARIO_COUNTING_STARTED =
- TEAMCITY_PREFIX + "[customProgressStatus testsCategory = 'Scenarios' count = '%s' timestamp = '%s']";
- private static final String TEMPLATE_SCENARIO_COUNTING_FINISHED =
- TEAMCITY_PREFIX + "[customProgressStatus testsCategory = '' count = '0' timestamp = '%s']";
- private static final String TEMPLATE_SCENARIO_STARTED = TEAMCITY_PREFIX + "[customProgressStatus type = 'testStarted' timestamp = '%s']";
- private static final String TEMPLATE_SCENARIO_FINISHED = TEAMCITY_PREFIX + "[customProgressStatus type = 'testFinished' timestamp = '%s']";
-
public static final String RESULT_STATUS_PENDING = "pending";
private Appendable appendable;
@@ -300,14 +272,6 @@ public class CucumberJvmSMFormatter implements Formatter, Reporter {
public void before(Match match, Result result) {
}
- private static String getCurrentTime() {
- return DATE_FORMAT.format(new Date());
- }
-
- private static String escape(String source) {
- return source.replace("|", "||").replace("\n", "|n").replace("\r", "|r").replace("'", "|'").replace("[", "|[").replace("]", "|]");
- }
-
private void outCommand(String s) {
outCommand(s, false);
}
diff --git a/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatterUtil.java b/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatterUtil.java
new file mode 100644
index 000000000000..c201cafdf31b
--- /dev/null
+++ b/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatterUtil.java
@@ -0,0 +1,43 @@
+package org.jetbrains.plugins.cucumber.java.run;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class CucumberJvmSMFormatterUtil {
+ public static final String TEAMCITY_PREFIX = "##teamcity";
+
+ public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSZ");
+
+ public static final String TEMPLATE_TEST_STARTED =
+ TEAMCITY_PREFIX + "[testStarted timestamp = '%s' locationHint = 'file:///%s' captureStandardOutput = 'true' name = '%s']";
+ public static final String TEMPLATE_TEST_FAILED =
+ TEAMCITY_PREFIX + "[testFailed timestamp = '%s' details = '%s' message = '%s' name = '%s' %s]";
+ public static final String TEMPLATE_SCENARIO_FAILED = TEAMCITY_PREFIX + "[customProgressStatus timestamp='%s' type='testFailed']";
+ public static final String TEMPLATE_TEST_PENDING =
+ TEAMCITY_PREFIX + "[testIgnored name = '%s' message = 'Skipped step' timestamp = '%s']";
+
+ public static final String TEMPLATE_TEST_FINISHED =
+ TEAMCITY_PREFIX +
+ "[testFinished timestamp = '%s' duration = '%s' name = '%s']";
+
+ public static final String TEMPLATE_ENTER_THE_MATRIX = TEAMCITY_PREFIX + "[enteredTheMatrix timestamp = '%s']";
+
+ public static final String TEMPLATE_TEST_SUITE_STARTED =
+ TEAMCITY_PREFIX + "[testSuiteStarted timestamp = '%s' locationHint = 'file://%s' name = '%s']";
+ public static final String TEMPLATE_TEST_SUITE_FINISHED = TEAMCITY_PREFIX + "[testSuiteFinished timestamp = '%s' name = '%s']";
+
+ public static final String TEMPLATE_SCENARIO_COUNTING_STARTED =
+ TEAMCITY_PREFIX + "[customProgressStatus testsCategory = 'Scenarios' count = '%s' timestamp = '%s']";
+ public static final String TEMPLATE_SCENARIO_COUNTING_FINISHED =
+ TEAMCITY_PREFIX + "[customProgressStatus testsCategory = '' count = '0' timestamp = '%s']";
+ public static final String TEMPLATE_SCENARIO_STARTED = TEAMCITY_PREFIX + "[customProgressStatus type = 'testStarted' timestamp = '%s']";
+ public static final String TEMPLATE_SCENARIO_FINISHED = TEAMCITY_PREFIX + "[customProgressStatus type = 'testFinished' timestamp = '%s']";
+
+ public static String getCurrentTime() {
+ return DATE_FORMAT.format(new Date());
+ }
+
+ public static String escape(String source) {
+ return source.replace("|", "||").replace("\n", "|n").replace("\r", "|r").replace("'", "|'").replace("[", "|[").replace("]", "|]");
+ }
+}