diff --git a/karate-core/src/main/java/com/intuit/karate/Suite.java b/karate-core/src/main/java/com/intuit/karate/Suite.java index 0a0aed328..eb1aa5b4b 100644 --- a/karate-core/src/main/java/com/intuit/karate/Suite.java +++ b/karate-core/src/main/java/com/intuit/karate/Suite.java @@ -224,6 +224,7 @@ public void run() { } hooks.forEach(h -> h.beforeSuite(this)); int index = 0; + List featureRuntimes = new ArrayList<>(featuresFound); for (FeatureCall feature : features) { final int featureNum = ++index; FeatureRuntime fr = FeatureRuntime.of(this, feature); @@ -233,11 +234,12 @@ public void run() { onFeatureDone(fr.result, featureNum); future.complete(Boolean.TRUE); }); - pendingTasks.submit(fr); + featureRuntimes.add(fr); } if (featuresFound > 1) { logger.debug("waiting for {} features to complete", featuresFound); } + featureRuntimes.forEach(pendingTasks::submit); CompletableFuture[] futuresArray = futures.toArray(new CompletableFuture[futures.size()]); if (timeoutMinutes > 0) { CompletableFuture.allOf(futuresArray).get(timeoutMinutes, TimeUnit.MINUTES); diff --git a/karate-core/src/test/java/com/intuit/karate/core/features/RemainingFeaturesTest.java b/karate-core/src/test/java/com/intuit/karate/core/features/RemainingFeaturesTest.java new file mode 100644 index 000000000..5241aeca9 --- /dev/null +++ b/karate-core/src/test/java/com/intuit/karate/core/features/RemainingFeaturesTest.java @@ -0,0 +1,44 @@ +package com.intuit.karate.core.features; + +import com.intuit.karate.Results; +import com.intuit.karate.Runner; +import com.intuit.karate.Suite; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class RemainingFeaturesTest { + + private static Suite suite; + + @Test + void testRemainingFeaturesSingleThread() { + verifyRemainingFeaturesWithThreads(1); + } + + @Test + void testRemainingFeaturesParallel() { + verifyRemainingFeaturesWithThreads(2); + } + + /** + * Hooks into the current suite to return the remaining features within the test + * @return Remaining features count + */ + public static long remainingFeatures() { + return suite.getFeaturesRemaining(); + } + + private void verifyRemainingFeaturesWithThreads(int threads) { + Runner.Builder builder = Runner.builder() + .path("classpath:com/intuit/karate/core/features") + .configDir("classpath:com/intuit/karate/core/features") + .threads(threads); + builder.resolveAll(); + suite = new Suite(builder); + suite.run(); + Results results = suite.buildResults(); + assertEquals(0, results.getFailCount(), results.getErrorMessages()); + } + +} diff --git a/karate-core/src/test/java/com/intuit/karate/core/features/feature1.feature b/karate-core/src/test/java/com/intuit/karate/core/features/feature1.feature new file mode 100644 index 000000000..db91445db --- /dev/null +++ b/karate-core/src/test/java/com/intuit/karate/core/features/feature1.feature @@ -0,0 +1,7 @@ +Feature: + + Scenario: feature test 1 + * def numOfFeaturesLeft = remainingFeatures() + * print 'Features left (including this one):', numOfFeaturesLeft + # this is the first feature that runs, so there should be more than 1 feature running + * assert numOfFeaturesLeft > 1 diff --git a/karate-core/src/test/java/com/intuit/karate/core/features/feature2.feature b/karate-core/src/test/java/com/intuit/karate/core/features/feature2.feature new file mode 100644 index 000000000..8703a1394 --- /dev/null +++ b/karate-core/src/test/java/com/intuit/karate/core/features/feature2.feature @@ -0,0 +1,7 @@ +Feature: + + Scenario: feature test 2 + * def numOfFeaturesLeft = remainingFeatures() + * print 'Features left (including this one):', numOfFeaturesLeft + # there should always be at least 1 feature left, even if it's the current feature running + * assert numOfFeaturesLeft >= 1 diff --git a/karate-core/src/test/java/com/intuit/karate/core/features/karate-config.js b/karate-core/src/test/java/com/intuit/karate/core/features/karate-config.js new file mode 100644 index 000000000..07fbe83d0 --- /dev/null +++ b/karate-core/src/test/java/com/intuit/karate/core/features/karate-config.js @@ -0,0 +1,8 @@ +function karateConfig() { + const config = {} + + const RemainingFeaturesTest = Java.type('com.intuit.karate.core.features.RemainingFeaturesTest') + config.remainingFeatures = RemainingFeaturesTest.remainingFeatures + + return config +} \ No newline at end of file