Cucumber-JVM: formatter for version 3 implemented.
authorAndrey Vokin <andrey.vokin@jetbrains.com>
Wed, 18 Jul 2018 14:26:38 +0000 (16:26 +0200)
committerAndrey Vokin <andrey.vokin@jetbrains.com>
Thu, 19 Jul 2018 12:28:15 +0000 (14:28 +0200)
In Cucumber for Java v.3 class 'TestStep' was changed to interface. That's why IncompatibleClassChangeError appeared when project with attached library v.3 was executed with SMFormatter compiled with library v.2

IDEA-192612 IncompatibleClassChangeError running Cucumber 3+ tests

build/cucumber-test-runner/intellij.cucumber.testRunner.iml
plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvm2SMFormatter.java
plugins/cucumber-jvm-formatter3/intellij.cucumber.jvmFormatter3.iml [new file with mode: 0644]
plugins/cucumber-jvm-formatter3/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvm3SMFormatter.java [new file with mode: 0644]

index e6a27d2b64e772a9dc3df0821995bbc8560e207f..6fce6df857755334353e43830c9cc509c1bd0fdb 100644 (file)
@@ -11,5 +11,6 @@
     <orderEntry type="module" module-name="intellij.platform.testFramework" />
     <orderEntry type="library" scope="PROVIDED" name="cucumber-core" level="project" />
     <orderEntry type="module" module-name="intellij.cucumber.jvmFormatter" scope="RUNTIME" />
+    <orderEntry type="module" module-name="intellij.cucumber.jvmFormatter3" scope="RUNTIME" />
   </component>
 </module>
\ No newline at end of file
index 3d14eda81029755aaff5a69975e2b1462038a222..b6d61dd01f12a3ac873b05338553382ba3737064 100644 (file)
@@ -88,39 +88,39 @@ public class CucumberJvm2SMFormatter implements Formatter {
 
   private void handleTestCaseStarted(TestCaseStarted event) {
     if (currentFilePath == null) {
-      outCommand(String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(), event.testCase.getUri(),
-                               getFeatureFileDescription(event.testCase.getUri())));
+      outCommand(String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(), getEventUri(event),
+                               getFeatureFileDescription(getEventUri(event))));
     }
-    else if (!event.testCase.getUri().equals(currentFilePath)) {
+    else if (!getEventUri(event).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())));
+      outCommand(String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(), getEventUri(event),
+                               getFeatureFileDescription(getEventUri(event))));
     }
 
     if (isScenarioOutline(event.testCase)) {
       int mainScenarioLine = getScenarioOutlineLine(event.testCase);
       if (currentScenarioOutlineLine != mainScenarioLine || currentFilePath == null ||
-          !currentFilePath.equals(event.testCase.getUri())) {
+          !currentFilePath.equals(getEventUri(event))) {
         closeCurrentScenarioOutline();
         currentScenarioOutlineLine = mainScenarioLine;
-        currentScenarioOutlineName = event.testCase.getName();
+        currentScenarioOutlineName = getEventName(event);
         outCommand(String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(),
-                                 event.testCase.getUri() + ":" + currentScenarioOutlineLine, currentScenarioOutlineName));
+                                 getEventUri(event) + ":" + currentScenarioOutlineLine, currentScenarioOutlineName));
         outCommand(String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(), "", EXAMPLES_CAPTION));
       }
     } else {
       closeCurrentScenarioOutline();
     }
-    currentFilePath = event.testCase.getUri();
+    currentFilePath = getEventUri(event);
 
     outCommand(String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(),
-                             event.testCase.getUri() + ":" + event.testCase.getLine(), getScenarioName(event.testCase)));
+                             getEventUri(event) + ":" + getEventLine(event), getScenarioName(event)));
   }
 
   private void handleTestCaseFinished(TestCaseFinished event) {
-    outCommand(String.format(TEMPLATE_TEST_SUITE_FINISHED, getCurrentTime(), getScenarioName(event.testCase)));
+    outCommand(String.format(TEMPLATE_TEST_SUITE_FINISHED, getCurrentTime(), getScenarioName(event)));
   }
 
   private void handleTestRunFinished(TestRunFinished event) {
@@ -129,21 +129,21 @@ public class CucumberJvm2SMFormatter implements Formatter {
                              getFeatureFileDescription(currentFilePath)));
   }
   private void handleTestStepStarted(TestStepStarted event) {
-    outCommand(String.format(TEMPLATE_TEST_STARTED, getCurrentTime(), getStepLocation(event.testStep),
-                             getStepName(event.testStep)));
+    outCommand(String.format(TEMPLATE_TEST_STARTED, getCurrentTime(), getStepLocation(event),
+                             getStepName(event)));
   }
 
   private void handleTestStepFinished(TestStepFinished event) {
     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()));
+      outCommand(String.format(TEMPLATE_TEST_PENDING, getStepName(event), getCurrentTime()));
     } else {
       outCommand(String.format(TEMPLATE_TEST_FAILED, getCurrentTime(), "",
-                               escape(event.result.getErrorMessage()), getStepName(event.testStep), ""));
+                               escape(event.result.getErrorMessage()), getStepName(event), ""));
     }
     Long duration = event.result.getDuration() != null ? event.result.getDuration() / 1000000: 0;
-    outCommand(String.format(TEMPLATE_TEST_FINISHED, getCurrentTime(), duration, getStepName(event.testStep)));
+    outCommand(String.format(TEMPLATE_TEST_FINISHED, getCurrentTime(), duration, getStepName(event)));
   }
 
   private String getFeatureFileDescription(String uri) {
@@ -238,6 +238,42 @@ public class CucumberJvm2SMFormatter implements Formatter {
     return escape(testCase.getName());
   }
 
+  protected String getScenarioName(TestCaseStarted testCaseStarted) {
+    return getScenarioName(testCaseStarted.testCase);
+  }
+
+  protected String getScenarioName(TestCaseFinished testCaseFinished) {
+    return getScenarioName(testCaseFinished.testCase);
+  }
+
+  protected String getEventUri(TestCaseStarted event) {
+    return event.testCase.getUri();
+  }
+
+  protected int getEventLine(TestCaseStarted event) {
+    return event.testCase.getLine();
+  }
+
+  protected String getEventName(TestCaseStarted event) {
+    return event.testCase.getName();
+  }
+
+  protected String getStepLocation(TestStepStarted testStepStarted) {
+    return getStepLocation(testStepStarted.testStep);
+  }
+
+  protected String getStepLocation(TestStepFinished testStepFinished) {
+    return getStepLocation(testStepFinished.testStep);
+  }
+
+  protected String getStepName(TestStepStarted testStepStarted) {
+    return getStepName(testStepStarted.testStep);
+  }
+
+  protected String getStepName(TestStepFinished testStepFinished) {
+    return getStepName(testStepFinished.testStep);
+  }
+
   private String getCurrentTime() {
     if (myCurrentTimeValue != null) {
       return myCurrentTimeValue;
diff --git a/plugins/cucumber-jvm-formatter3/intellij.cucumber.jvmFormatter3.iml b/plugins/cucumber-jvm-formatter3/intellij.cucumber.jvmFormatter3.iml
new file mode 100644 (file)
index 0000000..2d430f8
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" scope="PROVIDED" name="io.cucumber:cucumber-core:3.0.2" level="project" />
+    <orderEntry type="module" module-name="intellij.cucumber.jvmFormatter" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/plugins/cucumber-jvm-formatter3/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvm3SMFormatter.java b/plugins/cucumber-jvm-formatter3/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvm3SMFormatter.java
new file mode 100644 (file)
index 0000000..90b3822
--- /dev/null
@@ -0,0 +1,109 @@
+package org.jetbrains.plugins.cucumber.java.run;
+
+import cucumber.api.HookTestStep;
+import cucumber.api.PickleStepTestStep;
+import cucumber.api.TestCase;
+import cucumber.api.TestStep;
+import cucumber.api.event.TestCaseFinished;
+import cucumber.api.event.TestCaseStarted;
+import cucumber.api.event.TestStepFinished;
+import cucumber.api.event.TestStepStarted;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import static org.jetbrains.plugins.cucumber.java.run.CucumberJvmSMFormatterUtil.FILE_RESOURCE_PREFIX;
+import static org.jetbrains.plugins.cucumber.java.run.CucumberJvmSMFormatterUtil.escape;
+
+@SuppressWarnings("unused")
+public class CucumberJvm3SMFormatter extends CucumberJvm2SMFormatter {
+  public CucumberJvm3SMFormatter() {
+    super();
+  }
+
+  @Override
+  protected String getEventUri(TestCaseStarted event) {
+    return event.testCase.getUri();
+  }
+
+  @Override
+  protected int getEventLine(TestCaseStarted event) {
+    return event.testCase.getLine();
+  }
+
+  @Override
+  protected String getEventName(TestCaseStarted event) {
+    return event.testCase.getName();
+  }
+
+  @Override
+  protected String getScenarioName(TestCaseStarted testCaseStarted) {
+    return getScenarioName(testCaseStarted.testCase);
+  }
+
+  @Override
+  protected String getScenarioName(TestCaseFinished testCaseFinished) {
+    return getScenarioName(testCaseFinished.testCase);
+  }
+
+  @Override
+  protected String getStepLocation(TestStepStarted testStepStarted) {
+    return getStepLocation(testStepStarted.testStep);
+  }
+
+  @Override
+  protected String getStepLocation(TestStepFinished testStepFinished) {
+    return getStepLocation(testStepFinished.testStep);
+  }
+
+  @Override
+  protected String getStepName(TestStepStarted testStepStarted) {
+    return getStepName(testStepStarted.testStep);
+  }
+
+  @Override
+  protected String getStepName(TestStepFinished testStepFinished) {
+    return getStepName(testStepFinished.testStep);
+  }
+
+  private static String getScenarioName(TestCase testCase) {
+    return escape("Scenario: " + testCase.getName());
+  }
+
+  private static String getStepLocation(TestStep step) {
+    if (step instanceof HookTestStep) {
+      try {
+        Field definitionMatchField = step.getClass().getSuperclass().getDeclaredField("stepDefinitionMatch");
+        definitionMatchField.setAccessible(true);
+        Object definitionMatchFieldValue = definitionMatchField.get(step);
+
+        Field hookDefinitionField = definitionMatchFieldValue.getClass().getDeclaredField("hookDefinition");
+        hookDefinitionField.setAccessible(true);
+        Object hookDefinitionFieldValue = hookDefinitionField.get(definitionMatchFieldValue);
+
+        Field methodField = hookDefinitionFieldValue.getClass().getDeclaredField("method");
+        methodField.setAccessible(true);
+        Object methodFieldValue = methodField.get(hookDefinitionFieldValue);
+        if (methodFieldValue instanceof Method) {
+          Method method = (Method)methodFieldValue;
+          return String.format("java:test://%s/%s", method.getDeclaringClass().getName(), method.getName());
+        }
+      }
+      catch (Exception ignored) {
+      }
+      return "";
+    }
+    PickleStepTestStep pickleStepTestStep = (PickleStepTestStep) step;
+    return FILE_RESOURCE_PREFIX + pickleStepTestStep.getStepLocation() + ":" + pickleStepTestStep.getStepLine();
+  }
+
+  private static String getStepName(TestStep step) {
+    String stepName;
+    if (step instanceof HookTestStep) {
+      stepName = "Hook: " + ((HookTestStep)step).getHookType().toString();
+    } else {
+      stepName = ((PickleStepTestStep) step).getPickleStep().getText();
+    }
+    return escape(stepName);
+  }
+}