You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by js...@apache.org on 2021/05/19 12:09:20 UTC

[sling-org-apache-sling-junit-core] branch master updated: SLING-10394 - JUnit Core's HtmlReporter does not correctly report failed assumptions

This is an automated email from the ASF dual-hosted git repository.

jsedding pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-junit-core.git


The following commit(s) were added to refs/heads/master by this push:
     new 6be67ce  SLING-10394 - JUnit Core's HtmlReporter does not correctly report failed assumptions
6be67ce is described below

commit 6be67ce6ff4ad7674596cfb9045501a89e132cc9
Author: Julian Sedding <js...@apache.org>
AuthorDate: Wed May 19 14:03:15 2021 +0200

    SLING-10394 - JUnit Core's HtmlReporter does not correctly report failed assumptions
---
 pom.xml                                            |  31 ++++-
 .../sling/junit/impl/servlet/HtmlRenderer.java     |  20 ++-
 .../junit5/JUnit5TestExecutionStrategy.java        |  25 ++--
 .../junit/impl/servlet/junit5/ResultAdapter.java   |   2 +-
 .../impl/servlet/junit5/RunListenerAdapter.java    |  17 ++-
 .../sling/junit/impl/servlet/HtmlRendererTest.java | 139 +++++++++++++++++++++
 6 files changed, 216 insertions(+), 18 deletions(-)

diff --git a/pom.xml b/pom.xml
index 689c83b..9e68ab1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,14 +37,17 @@
         <junit.version>4.13</junit.version>
         <hamcrest.version>1.3</hamcrest.version>
         <jacoco.version>0.6.2.201302030002</jacoco.version>
+        <junit-jupiter.version>5.7.1</junit-jupiter.version>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
     </properties>
 
     <scm>
         <connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-junit-core.git</connection>
         <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-junit-core.git</developerConnection>
         <url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-junit-core.git</url>
-      <tag>HEAD</tag>
-  </scm>
+        <tag>HEAD</tag>
+    </scm>
 
     <build>
         <plugins>
@@ -313,11 +316,33 @@
         </dependency>
 
         <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <version>${junit-jupiter.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-params</artifactId>
+            <version>${junit-jupiter.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <version>${junit-jupiter.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
             <groupId>org.junit.vintage</groupId>
             <artifactId>junit-vintage-engine</artifactId>
-            <version>5.6.2</version>
+            <version>${junit-jupiter.version}</version>
             <scope>test</scope>
         </dependency>
+
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
diff --git a/src/main/java/org/apache/sling/junit/impl/servlet/HtmlRenderer.java b/src/main/java/org/apache/sling/junit/impl/servlet/HtmlRenderer.java
index fc00239..4120128 100644
--- a/src/main/java/org/apache/sling/junit/impl/servlet/HtmlRenderer.java
+++ b/src/main/java/org/apache/sling/junit/impl/servlet/HtmlRenderer.java
@@ -103,7 +103,7 @@ public class HtmlRenderer extends RunListener implements Renderer,RendererFactor
         }
         response.setContentType("text/html");
         response.setCharacterEncoding("UTF-8");
-        output = response.getWriter();
+        setWriter(response.getWriter());
         output.println("<html><head>");
         output.println("<link rel='stylesheet' type='text/css' href='" + ServletProcessor.CSS + "'/>");
         output.print("<title>");
@@ -114,6 +114,10 @@ public class HtmlRenderer extends RunListener implements Renderer,RendererFactor
         output.println("</h1>");
     }
 
+    public void setWriter(PrintWriter writer) {
+        output = writer;
+    }
+
     public void cleanup() {
         output.println("</body>");
         output.println("</html>");
@@ -125,6 +129,18 @@ public class HtmlRenderer extends RunListener implements Renderer,RendererFactor
     }
 
     @Override
+    public void testAssumptionFailure(Failure failure) {
+        super.testAssumptionFailure(failure);
+        output.print("<p class='ignored'><h3>TEST ABORTED</h3><b>");
+        String message = failure.getMessage();
+        if (!message.startsWith("Assumption failed: ")) {
+            message = "Assumption failed: " + message;
+        }
+        HtmlFilter.escape(output, message);
+        output.println("</b></p>");
+    }
+
+    @Override
     public void testFailure(Failure failure) throws Exception {
         super.testFailure(failure);
         output.print("<div class='failure'><h3>");
@@ -176,6 +192,8 @@ public class HtmlRenderer extends RunListener implements Renderer,RendererFactor
         counter("failures", "failureCount", result.getFailureCount());
         output.print(", ");
         counter("ignored", "ignoredCount", result.getIgnoreCount());
+        output.print(", ");
+        counter("aborted", "abortedCount", result.getAssumptionFailureCount());
         output.println("</p>");
     }
 
diff --git a/src/main/java/org/apache/sling/junit/impl/servlet/junit5/JUnit5TestExecutionStrategy.java b/src/main/java/org/apache/sling/junit/impl/servlet/junit5/JUnit5TestExecutionStrategy.java
index 52c4c00..7363374 100644
--- a/src/main/java/org/apache/sling/junit/impl/servlet/junit5/JUnit5TestExecutionStrategy.java
+++ b/src/main/java/org/apache/sling/junit/impl/servlet/junit5/JUnit5TestExecutionStrategy.java
@@ -21,7 +21,9 @@ package org.apache.sling.junit.impl.servlet.junit5;
 import org.apache.sling.junit.TestSelector;
 import org.apache.sling.junit.impl.TestExecutionStrategy;
 import org.apache.sling.junit.impl.TestsManagerImpl;
+import org.jetbrains.annotations.NotNull;
 import org.junit.platform.engine.DiscoverySelector;
+import org.junit.platform.engine.TestEngine;
 import org.junit.platform.engine.discovery.DiscoverySelectors;
 import org.junit.platform.launcher.Launcher;
 import org.junit.platform.launcher.LauncherDiscoveryRequest;
@@ -71,27 +73,34 @@ public class JUnit5TestExecutionStrategy implements TestExecutionStrategy {
 
     @Override
     public void execute(TestSelector selector, RunListener runListener) throws Exception {
-        Launcher launcher = LauncherFactory.create(
+        Launcher launcher = createLauncher(runListener, testEngineTracker.getAvailableTestEngines());
+        final LauncherDiscoveryRequest request = testsManager.createTestRequest(selector,
+                JUnit5TestExecutionStrategy::methodRequest,
+                JUnit5TestExecutionStrategy::classesRequest);
+        launcher.execute(request);
+    }
+
+    @NotNull
+    public static Launcher createLauncher(RunListener runListener, TestEngine... availableTestEngines) {
+        return LauncherFactory.create(
                 LauncherConfig.builder()
-                        .addTestEngines(testEngineTracker.getAvailableTestEngines())
+                        .addTestEngines(availableTestEngines)
                         .addTestExecutionListeners(new RunListenerAdapter(runListener))
                         .enableTestEngineAutoRegistration(false)
                         .enableTestExecutionListenerAutoRegistration(false)
                         .build()
         );
-
-        final LauncherDiscoveryRequest request =
-                testsManager.createTestRequest(selector, this::methodRequest, this::classesRequest);
-        launcher.execute(request);
     }
 
-    private LauncherDiscoveryRequest methodRequest(Class<?> testClass, String testMethodName) {
+    @NotNull
+    public static LauncherDiscoveryRequest methodRequest(Class<?> testClass, String testMethodName) {
         return LauncherDiscoveryRequestBuilder.request()
                 .selectors(selectMethod(testClass, testMethodName))
                 .build();
     }
 
-    private LauncherDiscoveryRequest classesRequest(Class<?>[] testClasses) {
+    @NotNull
+    public static LauncherDiscoveryRequest classesRequest(Class<?>... testClasses) {
         final DiscoverySelector[] selectors = Stream.of(testClasses)
                 .map(DiscoverySelectors::selectClass)
                 .toArray(DiscoverySelector[]::new);
diff --git a/src/main/java/org/apache/sling/junit/impl/servlet/junit5/ResultAdapter.java b/src/main/java/org/apache/sling/junit/impl/servlet/junit5/ResultAdapter.java
index 8119527..3241aa7 100644
--- a/src/main/java/org/apache/sling/junit/impl/servlet/junit5/ResultAdapter.java
+++ b/src/main/java/org/apache/sling/junit/impl/servlet/junit5/ResultAdapter.java
@@ -65,7 +65,7 @@ public class ResultAdapter extends Result {
 
     @Override
     public int getAssumptionFailureCount() {
-        return 0;
+        return (int) summary.getTestsAbortedCount();
     }
 
     @Override
diff --git a/src/main/java/org/apache/sling/junit/impl/servlet/junit5/RunListenerAdapter.java b/src/main/java/org/apache/sling/junit/impl/servlet/junit5/RunListenerAdapter.java
index 67c73fc..d598ade 100644
--- a/src/main/java/org/apache/sling/junit/impl/servlet/junit5/RunListenerAdapter.java
+++ b/src/main/java/org/apache/sling/junit/impl/servlet/junit5/RunListenerAdapter.java
@@ -91,12 +91,19 @@ public class RunListenerAdapter implements TestExecutionListener {
     public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) {
         summarizer.executionFinished(testIdentifier, testExecutionResult);
         if (testIdentifier.isTest()) {
-            if (testExecutionResult.getStatus() != TestExecutionResult.Status.SUCCESSFUL) {
-                try {
-                    runListener.testFailure(FailureHelper.convert(testIdentifier, testExecutionResult.getThrowable().orElse(null)));
-                } catch (Exception exception) {
-                    throw new RuntimeException(exception);
+            try {
+                switch (testExecutionResult.getStatus()) {
+                    case FAILED:
+                        runListener.testFailure(FailureHelper.convert(testIdentifier, testExecutionResult.getThrowable().orElse(null)));
+                        break;
+                    case ABORTED:
+                        runListener.testAssumptionFailure(FailureHelper.convert(testIdentifier, testExecutionResult.getThrowable().orElse(null)));
+                        break;
+                    case SUCCESSFUL:
+                        break;
                 }
+            } catch (Exception exception) {
+                throw new RuntimeException(exception);
             }
             withDescription(testIdentifier, runListener::testFinished);
         } else {
diff --git a/src/test/java/org/apache/sling/junit/impl/servlet/HtmlRendererTest.java b/src/test/java/org/apache/sling/junit/impl/servlet/HtmlRendererTest.java
new file mode 100644
index 0000000..dd86d3d
--- /dev/null
+++ b/src/test/java/org/apache/sling/junit/impl/servlet/HtmlRendererTest.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.junit.impl.servlet;
+
+import org.apache.sling.junit.impl.servlet.junit5.JUnit5TestExecutionStrategy;
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.engine.JupiterTestEngine;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.platform.engine.TestEngine;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.runner.notification.RunListener;
+import org.junit.vintage.engine.VintageTestEngine;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.stream.Stream;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class HtmlRendererTest {
+
+    @SuppressWarnings("unused")
+    private static Stream<Arguments> testEngines() {
+        return Stream.of(
+                Arguments.of("junit4", new VintageTestEngine()),
+                Arguments.of("jupiter", new JupiterTestEngine())
+        );
+    }
+
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("testEngines")
+    public void testInvalidAssumption(String prefix, TestEngine testEngine) {
+        String html = renderHtmlOutput(testEngine, ExampleTestCases.class, prefix + "FailedAssumption");
+        assertThat(html, Matchers.containsString(
+                String.format("<p class='ignored'><h3>TEST ABORTED</h3><b>Assumption failed: %s</b></p>",
+                        ExampleTestCases.ASSUMPTION_IS_ALWAYS_INVALID)));
+        assertThat(html, Matchers.containsString("<span class='testCountNonZero'>tests:1</span>"));
+        assertThat(html, Matchers.containsString("<span class='abortedCountNonZero'>aborted:1</span>"));
+    }
+
+    @ParameterizedTest
+    @MethodSource("testEngines")
+    public void testFailure(String prefix, TestEngine testEngine) {
+        final String failedAssertion = "FailedAssertion";
+        String html = renderHtmlOutput(testEngine, ExampleTestCases.class, prefix + failedAssertion);
+        assertThat(html, Matchers.containsString("class='failure'"));
+        assertThat(html, Matchers.containsString("class='failureDetails'"));
+        assertThat(html, Matchers.containsString(String.format("<h3>TEST FAILED: %s%s(%s)</h3>", prefix, failedAssertion, ExampleTestCases.class.getName())));
+        assertThat(html, Matchers.containsString(ExampleTestCases.ASSERTION_ALWAYS_FAILS));
+        assertThat(html, Matchers.containsString("<span class='testCountNonZero'>tests:1</span>"));
+        assertThat(html, Matchers.containsString("<span class='failureCountNonZero'>failures:1</span>"));
+    }
+
+    @ParameterizedTest
+    @MethodSource("testEngines")
+    public void testSuccess(String prefix, TestEngine testEngine) {
+        String html = renderHtmlOutput(testEngine, ExampleTestCases.class, prefix + "Success");
+        assertThat(html, Matchers.containsString("<span class='testCountNonZero'>tests:1</span>"));
+        assertThat(html, Matchers.containsString("<span class='failureCountZero'>failures:0</span>"));
+    }
+
+    private static String renderHtmlOutput(TestEngine testEngine, Class<ExampleTestCases> testClass, String methodName) {
+        final StringWriter out = new StringWriter();
+        final HtmlRenderer htmlRenderer = new HtmlRenderer();
+        htmlRenderer.setWriter(new PrintWriter(out));
+        runTest(testEngine, htmlRenderer, testClass, methodName);
+        return out.toString();
+    }
+
+    private static void runTest(TestEngine testEngine, RunListener runListener, Class<?> testClass, String methodName) {
+        final Launcher launcher = JUnit5TestExecutionStrategy.createLauncher(runListener, testEngine);
+        final LauncherDiscoveryRequest request = methodName != null
+                ? JUnit5TestExecutionStrategy.methodRequest(testClass, methodName)
+                : JUnit5TestExecutionStrategy.classesRequest(testClass);
+        launcher.execute(request);
+    }
+
+    public static class ExampleTestCases {
+
+        public static final String ASSUMPTION_IS_ALWAYS_INVALID = "Assumption is always invalid";
+
+        public static final String ASSERTION_ALWAYS_FAILS = "Assertion always fails";
+
+        public static final String ASSERTION_ALWAYS_SUCCEEDS = "Assertion always succeeds";
+
+        @org.junit.jupiter.api.Test
+        public void jupiterFailedAssumption() {
+            Assumptions.assumeFalse(true, ASSUMPTION_IS_ALWAYS_INVALID);
+        }
+
+        @org.junit.jupiter.api.Test
+        public void jupiterFailedAssertion() {
+            Assertions.fail(ASSERTION_ALWAYS_FAILS);
+        }
+
+        @org.junit.jupiter.api.Test
+        public void jupiterSuccess() {
+            Assertions.assertTrue(true, ASSERTION_ALWAYS_SUCCEEDS);
+        }
+
+        @org.junit.Test
+        public void junit4FailedAssumption() {
+            Assume.assumeFalse(ASSUMPTION_IS_ALWAYS_INVALID, true);
+        }
+
+        @org.junit.Test
+        public void junit4FailedAssertion() {
+            Assert.fail(ASSERTION_ALWAYS_FAILS);
+        }
+
+        @org.junit.Test
+        public void junit4Success() {
+            Assert.assertTrue(ASSERTION_ALWAYS_SUCCEEDS, true);
+        }
+    }
+}
\ No newline at end of file