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 d13feac68e908..7e9a6c1af063b 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 @@ -140,6 +140,7 @@ public void runTests() { currentTestAppConsumer.accept(testApplication); Set allDiscoveredIds = new HashSet<>(); + Set dynamicIds = new HashSet<>(); try (DiscoveryResult quarkusTestClasses = discoverTestClasses(devModeContext)) { Launcher launcher = LauncherFactory.create(LauncherConfig.builder().build()); @@ -177,7 +178,7 @@ public FilterResult apply(TestDescriptor testDescriptor) { .build(); TestPlan testPlan = launcher.discover(request); if (!testPlan.containsTests()) { - testState.pruneDeletedTests(allDiscoveredIds); + testState.pruneDeletedTests(allDiscoveredIds, dynamicIds); //nothing to see here for (TestRunListener i : listeners) { i.noTests(new TestRunResults(runId, classScanResult, classScanResult == null, start, @@ -271,6 +272,11 @@ public void executionSkipped(TestIdentifier testIdentifier, String reason) { touchedClasses.push(Collections.synchronizedSet(new HashSet<>())); } + @Override + public void dynamicTestRegistered(TestIdentifier testIdentifier) { + dynamicIds.add(UniqueId.parse(testIdentifier.getUniqueId())); + } + @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { @@ -362,7 +368,7 @@ public void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry e return; } testState.updateResults(resultsByClass); - testState.pruneDeletedTests(allDiscoveredIds); + testState.pruneDeletedTests(allDiscoveredIds, dynamicIds); if (classScanResult != null) { testState.classesRemoved(classScanResult.getDeletedClassNames()); } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestState.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestState.java index e386ab61c284d..95133c2a60d59 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestState.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestState.java @@ -17,6 +17,7 @@ public class TestState { final Map> resultsByClass = new HashMap<>(); final Set failing = new HashSet<>(); + final Set dynamicIds = new HashSet<>(); public List getClassNames() { return new ArrayList<>(resultsByClass.keySet()).stream().sorted().collect(Collectors.toList()); @@ -132,10 +133,25 @@ public boolean isFailed(TestDescriptor testDescriptor) { return failing.contains(testDescriptor.getUniqueId()); } - public void pruneDeletedTests(Set allDiscoveredIds) { - failing.removeIf(i -> !allDiscoveredIds.contains(i)); + public void pruneDeletedTests(Set allDiscoveredIds, Set dynamicIds) { + Set dynamicParents = dynamicIds.stream().map(UniqueId::removeLastSegment).collect(Collectors.toSet()); + this.dynamicIds.removeIf(s -> { + //was actually run, don't remove + if (dynamicIds.contains(s)) { + return false; + } + UniqueId parent = s.removeLastSegment(); + //parent was run, but not this test, so it has been removed + if (dynamicParents.contains(parent)) { + return true; + } + return !allDiscoveredIds.contains(parent); + }); + this.dynamicIds.addAll(dynamicIds); + failing.removeIf(i -> (!allDiscoveredIds.contains(i) && !this.dynamicIds.contains(i))); for (Map.Entry> cr : resultsByClass.entrySet()) { - cr.getValue().entrySet().removeIf(s -> !allDiscoveredIds.contains(s.getKey())); + cr.getValue().entrySet() + .removeIf(s -> (!allDiscoveredIds.contains(s.getKey()) && !this.dynamicIds.contains(s.getKey()))); } resultsByClass.entrySet().removeIf(s -> s.getValue().isEmpty()); } diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/HelloResource.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/HelloResource.java new file mode 100644 index 0000000000000..38c8730a0ca07 --- /dev/null +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/HelloResource.java @@ -0,0 +1,13 @@ +package io.quarkus.vertx.http.testrunner.params; + +import io.vertx.core.Handler; +import io.vertx.ext.web.RoutingContext; + +public class HelloResource implements Handler { + + @Override + public void handle(RoutingContext event) { + event.response().end("hello"); + } + +} diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/OddResource.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/OddResource.java new file mode 100644 index 0000000000000..96b5080cefeae --- /dev/null +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/OddResource.java @@ -0,0 +1,13 @@ +package io.quarkus.vertx.http.testrunner.params; + +import io.vertx.core.Handler; +import io.vertx.ext.web.RoutingContext; + +public class OddResource implements Handler { + + @Override + public void handle(RoutingContext event) { + event.response().end(Boolean.toString(Integer.parseInt(event.pathParam("num")) % 2 == 1)); + } + +} diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/ParamET.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/ParamET.java new file mode 100644 index 0000000000000..811f8e0163af9 --- /dev/null +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/ParamET.java @@ -0,0 +1,33 @@ +package io.quarkus.vertx.http.testrunner.params; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.is; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class ParamET { + + @Test + public void testHelloEndpoint() { + given() + .when().get("/hello") + .then() + .statusCode(200) + .body(is("hello")); + } + + @ParameterizedTest + @ValueSource(ints = { 1, 4, 11, 17 }) + void shouldValidateOddNumbers(int x) { + given() + .when().get("/odd/" + x) + .then() + .statusCode(200) + .body(is("true")); + } +} diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/Setup.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/Setup.java new file mode 100644 index 0000000000000..53bd7f3d0021e --- /dev/null +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/Setup.java @@ -0,0 +1,16 @@ +package io.quarkus.vertx.http.testrunner.params; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; + +import io.vertx.ext.web.Router; + +@ApplicationScoped +public class Setup { + + public void route(@Observes Router router) { + router.route("/hello").handler(new HelloResource()); + router.route("/odd/:num").handler(new OddResource()); + } + +} 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 new file mode 100644 index 0000000000000..fa4dbe9dfc93c --- /dev/null +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/params/TestParameterizedTestCase.java @@ -0,0 +1,74 @@ +package io.quarkus.vertx.http.testrunner.params; + +import java.util.function.Function; +import java.util.function.Supplier; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusDevModeTest; +import io.quarkus.vertx.http.deployment.devmode.tests.TestStatus; +import io.quarkus.vertx.http.testrunner.ContinuousTestingTestUtils; + +public class TestParameterizedTestCase { + + @RegisterExtension + static QuarkusDevModeTest test = new QuarkusDevModeTest() + .setArchiveProducer(new Supplier() { + @Override + public JavaArchive get() { + return ShrinkWrap.create(JavaArchive.class).addClasses(OddResource.class, Setup.class, HelloResource.class) + .add(new StringAsset(ContinuousTestingTestUtils.appProperties()), + "application.properties"); + } + }) + .setTestArchiveProducer(new Supplier() { + @Override + public JavaArchive get() { + return ShrinkWrap.create(JavaArchive.class).addClass(ParamET.class); + } + }); + + @Test + public void testParameterizedTests() throws InterruptedException { + TestStatus ts = ContinuousTestingTestUtils.waitForFirstRunToComplete(); + Assertions.assertEquals(1L, ts.getLastRun()); + Assertions.assertEquals(1L, ts.getTestsFailed()); + Assertions.assertEquals(4L, ts.getTestsPassed()); + Assertions.assertEquals(0L, ts.getTestsSkipped()); + Assertions.assertEquals(-1L, ts.getRunning()); + + test.modifyTestSourceFile(ParamET.class, new Function() { + @Override + public String apply(String s) { + return s.replace("4", "3"); + } + }); + ts = ContinuousTestingTestUtils.waitForRun(2); + Assertions.assertEquals(2L, ts.getLastRun()); + Assertions.assertEquals(0L, ts.getTestsFailed()); + Assertions.assertEquals(5L, ts.getTestsPassed()); //passing test should not have been run + Assertions.assertEquals(0L, ts.getTestsSkipped()); + Assertions.assertEquals(-1L, ts.getRunning()); + Assertions.assertEquals(5L, ts.getTotalTestsPassed()); + + test.modifySourceFile(HelloResource.class, new Function() { + @Override + public String apply(String s) { + return s.replace("hello", "boo"); + } + }); + ts = ContinuousTestingTestUtils.waitForRun(3); + Assertions.assertEquals(3L, ts.getLastRun()); + Assertions.assertEquals(1L, ts.getTestsFailed()); + Assertions.assertEquals(0L, ts.getTestsPassed()); + Assertions.assertEquals(4L, ts.getTotalTestsPassed()); + Assertions.assertEquals(0L, ts.getTestsSkipped()); + Assertions.assertEquals(-1L, ts.getRunning()); + + } +}