diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/ContinuousTestingSharedStateListener.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/ContinuousTestingSharedStateListener.java index 85da540feb584..2e965d7724671 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/ContinuousTestingSharedStateListener.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/ContinuousTestingSharedStateListener.java @@ -67,11 +67,6 @@ public void runComplete(TestRunResults testRunResults) { }); } - @Override - public void noTests(TestRunResults results) { - runComplete(results); - } - @Override public void runAborted() { ContinuousTestingSharedStateManager.setInProgress(false); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/JunitTestRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/JunitTestRunner.java index 1bce4eaedfd25..a43da33c5d45a 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/JunitTestRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/JunitTestRunner.java @@ -178,21 +178,6 @@ public FilterResult apply(TestDescriptor testDescriptor) { LauncherDiscoveryRequest request = launchBuilder .build(); TestPlan testPlan = launcher.discover(request); - if (!testPlan.containsTests()) { - testState.pruneDeletedTests(allDiscoveredIds, dynamicIds); - //nothing to see here - for (TestRunListener i : listeners) { - i.noTests(new TestRunResults(runId, classScanResult, classScanResult == null, start, - System.currentTimeMillis(), toResultsMap(testState.getCurrentResults()))); - } - quarkusTestClasses.close(); - return new Runnable() { - @Override - public void run() { - - } - }; - } long toRun = testPlan.countTestIdentifiers(TestIdentifier::isTest); for (TestRunListener listener : listeners) { listener.runStarted(toRun); @@ -226,6 +211,7 @@ public void quarkusStarting() { }); Map> resultsByClass = new HashMap<>(); + AtomicReference currentNonDynamicTest = new AtomicReference<>(); launcher.execute(testPlan, new TestExecutionListener() { @Override @@ -233,6 +219,10 @@ public void executionStarted(TestIdentifier testIdentifier) { if (aborted) { return; } + boolean dynamic = dynamicIds.contains(UniqueId.parse(testIdentifier.getUniqueId())); + if (!dynamic) { + currentNonDynamicTest.set(testIdentifier); + } startTimes.put(testIdentifier, System.currentTimeMillis()); String testClassName = ""; Class testClass = getTestClassFromSource(testIdentifier.getSource()); @@ -260,7 +250,7 @@ public void executionSkipped(TestIdentifier testIdentifier, String reason) { s -> new HashMap<>()); TestResult result = new TestResult(displayName, testClass.getName(), id, TestExecutionResult.aborted(null), - logHandler.captureOutput(), testIdentifier.isTest(), runId, 0); + logHandler.captureOutput(), testIdentifier.isTest(), runId, 0, true); results.put(id, result); if (result.isTest()) { for (TestRunListener listener : listeners) { @@ -274,6 +264,9 @@ public void executionSkipped(TestIdentifier testIdentifier, String reason) { @Override public void dynamicTestRegistered(TestIdentifier testIdentifier) { dynamicIds.add(UniqueId.parse(testIdentifier.getUniqueId())); + for (TestRunListener listener : listeners) { + listener.dynamicTestRegistered(testIdentifier); + } } @Override @@ -282,6 +275,7 @@ public void executionFinished(TestIdentifier testIdentifier, if (aborted) { return; } + boolean dynamic = dynamicIds.contains(UniqueId.parse(testIdentifier.getUniqueId())); Set touched = touchedClasses.pop(); Class testClass = getTestClassFromSource(testIdentifier.getSource()); String displayName = getDisplayNameFromIdentifier(testIdentifier, testClass); @@ -306,18 +300,33 @@ public void executionFinished(TestIdentifier testIdentifier, testClassUsages.updateTestData(testClassName, id, touched); } } - Map results = resultsByClass.computeIfAbsent(testClassName, s -> new HashMap<>()); TestResult result = new TestResult(displayName, testClassName, id, testExecutionResult, logHandler.captureOutput(), testIdentifier.isTest(), runId, - System.currentTimeMillis() - startTimes.get(testIdentifier)); - results.put(id, result); + System.currentTimeMillis() - startTimes.get(testIdentifier), true); + if (!results.containsKey(id)) { + //if a child has failed we may have already marked the parent failed + results.put(id, result); + } if (result.isTest()) { for (TestRunListener listener : listeners) { listener.testComplete(result); } + if (dynamic && testExecutionResult.getStatus() == TestExecutionResult.Status.FAILED) { + //if it is dynamic we fail the parent as well for re-runs + + RuntimeException failure = new RuntimeException("A child test failed"); + failure.setStackTrace(new StackTraceElement[0]); + results.put(id, + new TestResult(currentNonDynamicTest.get().getDisplayName(), + result.getTestClass(), + currentNonDynamicTest.get().getUniqueIdObject(), + TestExecutionResult.failed(failure), List.of(), false, runId, 0, + false)); + results.put(UniqueId.parse(currentNonDynamicTest.get().getUniqueId()), result); + } } else if (testExecutionResult.getStatus() == TestExecutionResult.Status.FAILED) { //if a parent fails we fail the children Set children = testPlan.getChildren(testIdentifier); @@ -327,7 +336,7 @@ public void executionFinished(TestIdentifier testIdentifier, childId, testExecutionResult, logHandler.captureOutput(), child.isTest(), runId, - System.currentTimeMillis() - startTimes.get(testIdentifier)); + System.currentTimeMillis() - startTimes.get(testIdentifier), true); results.put(childId, result); if (child.isTest()) { for (TestRunListener listener : listeners) { diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestConsoleHandler.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestConsoleHandler.java index 764b66944c359..9225b2b8fc46d 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestConsoleHandler.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestConsoleHandler.java @@ -220,9 +220,11 @@ public void runComplete(TestRunResults results) { log.error(statusHeader("TEST REPORT #" + results.getId())); for (Map.Entry classEntry : results.getCurrentFailing().entrySet()) { for (TestResult test : classEntry.getValue().getFailing()) { - log.error( - RED + "Test " + test.getDisplayName() + " failed \n" + RESET, - test.getTestExecutionResult().getThrowable().get()); + if (test.isReportable()) { + log.error( + RED + "Test " + test.getDisplayName() + " failed \n" + RESET, + test.getTestExecutionResult().getThrowable().get()); + } } } log.error( @@ -244,11 +246,6 @@ public void runComplete(TestRunResults results) { } } - @Override - public void noTests(TestRunResults results) { - runComplete(results); - } - @Override public void runAborted() { firstRun = false; @@ -268,6 +265,11 @@ public void testStarted(TestIdentifier testIdentifier, String className) { } testsStatusOutput.setMessage(status); } + + @Override + public void dynamicTestRegistered(TestIdentifier testIdentifier) { + totalNoTests.incrementAndGet(); + } }); } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestResult.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestResult.java index 44e278c986e81..4250d332492dc 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestResult.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestResult.java @@ -18,9 +18,10 @@ public class TestResult { final long runId; final long time; final List problems; + final boolean reportable; public TestResult(String displayName, String testClass, UniqueId uniqueId, TestExecutionResult testExecutionResult, - List logOutput, boolean test, long runId, long time) { + List logOutput, boolean test, long runId, long time, boolean reportable) { this.displayName = displayName; this.testClass = testClass; this.uniqueId = uniqueId; @@ -29,6 +30,7 @@ public TestResult(String displayName, String testClass, UniqueId uniqueId, TestE this.test = test; this.runId = runId; this.time = time; + this.reportable = reportable; List problems = new ArrayList<>(); if (testExecutionResult.getThrowable().isPresent()) { Throwable t = testExecutionResult.getThrowable().get(); @@ -75,4 +77,8 @@ public long getTime() { public List getProblems() { return problems; } + + public boolean isReportable() { + return reportable; + } } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestRunListener.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestRunListener.java index 5a817d1857623..0f3e8278d4093 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestRunListener.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestRunListener.java @@ -24,7 +24,7 @@ default void testStarted(TestIdentifier testIdentifier, String className) { } - default void noTests(TestRunResults results) { + default void dynamicTestRegistered(TestIdentifier testIdentifier) { } } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestSupport.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestSupport.java index 1ac18ade9c3a8..01d76c061843c 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestSupport.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestSupport.java @@ -374,20 +374,8 @@ public void testStarted(TestIdentifier testIdentifier, String className) { } } - @Override - public void noTests(TestRunResults results) { - allResults.add(results); - runStarted(0); - } })); } - if (testCount.get() == 0) { - TestRunResults results = new TestRunResults(runId, classScanResult, classScanResult == null, start, - System.currentTimeMillis(), Collections.emptyMap()); - for (var i : testRunListeners) { - i.noTests(results); - } - } for (var i : testRunListeners) { i.runStarted(testCount.get()); } diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/tests/TestsProcessor.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/tests/TestsProcessor.java index 3a0ac541a62a5..5d8ee7d0ce9a5 100644 --- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/tests/TestsProcessor.java +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/tests/TestsProcessor.java @@ -146,6 +146,7 @@ DevConsoleRouteBuildItem runAllTests(LaunchModeBuildItem launchModeBuildItem) { @Override public void handle(RoutingContext event) { ts.get().runAllTests(); + event.response().setStatusCode(204).end(); } }); } @@ -178,6 +179,7 @@ DevConsoleRouteBuildItem runFailedTests(LaunchModeBuildItem launchModeBuildItem) @Override public void handle(RoutingContext event) { ts.get().runFailedTests(); + event.response().setStatusCode(204).end(); } }); } @@ -192,6 +194,7 @@ DevConsoleRouteBuildItem printfailures(LaunchModeBuildItem launchModeBuildItem) @Override public void handle(RoutingContext event) { ts.get().printFullResults(); + event.response().setStatusCode(204).end(); } }); } @@ -235,6 +238,7 @@ DevConsoleRouteBuildItem forceRestart(LaunchModeBuildItem launchModeBuildItem) { @Override public void handle(RoutingContext event) { RuntimeUpdatesProcessor.INSTANCE.doScan(true, true); + event.response().setStatusCode(204).end(); } }); } diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/TestParameterizedTestCase.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/TestParameterizedTestCase.java index 57c14bc6694f1..1c85ca3dd131b 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/TestParameterizedTestCase.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/TestParameterizedTestCase.java @@ -13,6 +13,7 @@ import io.quarkus.test.ContinuousTestingTestUtils; import io.quarkus.test.ContinuousTestingTestUtils.TestStatus; import io.quarkus.test.QuarkusDevModeTest; +import io.restassured.RestAssured; public class TestParameterizedTestCase { @@ -42,6 +43,13 @@ public void testParameterizedTests() throws InterruptedException { Assertions.assertEquals(4L, ts.getTestsPassed()); Assertions.assertEquals(0L, ts.getTestsSkipped()); + RestAssured.post("q/dev/io.quarkus.quarkus-vertx-http/tests/runfailed"); + + ts = utils.waitForNextCompletion(); + + Assertions.assertEquals(1L, ts.getTestsFailed()); + Assertions.assertEquals(3L, ts.getTestsPassed()); //they are all re-run + Assertions.assertEquals(0L, ts.getTestsSkipped()); test.modifyTestSourceFile(ParamET.class, new Function() { @Override public String apply(String s) {