diff --git a/spock-core/src/main/java/org/spockframework/runtime/SpecProcessor.java b/spock-core/src/main/java/org/spockframework/runtime/SpecProcessor.java index b575c857ed..fb65b25180 100644 --- a/spock-core/src/main/java/org/spockframework/runtime/SpecProcessor.java +++ b/spock-core/src/main/java/org/spockframework/runtime/SpecProcessor.java @@ -1,9 +1,21 @@ package org.spockframework.runtime; +import org.spockframework.runtime.extension.builtin.orderer.SpecOrderer; import org.spockframework.runtime.model.SpecInfo; import java.util.Collection; +/** + * Generic bulk processor for a collection of {@link SpecInfo} elements + * + * @see SpecOrderer + */ public interface SpecProcessor { + /** + * Bulk-process a collection of {@link SpecInfo} elements in-place, i.e. do not return anything but operate on the + * elements given, changing their state if necessary. + * + * @param specs spec-info instances to be processed + */ void process(Collection specs); } diff --git a/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/AlphabeticalSpecOrderer.java b/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/AlphabeticalSpecOrderer.java index 877efed593..ce1dc88c4d 100644 --- a/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/AlphabeticalSpecOrderer.java +++ b/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/AlphabeticalSpecOrderer.java @@ -1,22 +1,46 @@ package org.spockframework.runtime.extension.builtin.orderer; +import org.spockframework.runtime.model.FeatureInfo; import org.spockframework.runtime.model.SpecInfo; import java.util.Collection; import java.util.concurrent.atomic.AtomicInteger; +/** + * Orderer capable of assigning specification and/or feature method run orders according to spec/feature display names, + * comparing them alphabetically. There is no locale-specific collation, only simple string comparison based on the + * default JVM locale, using by {@link String#compareTo(String)}. + */ public class AlphabeticalSpecOrderer extends SpecOrderer { private final boolean ascending; + /** + * Create an alphabetical spec orderer + * + * @param orderSpecs modify specification run order (yes/no)? + * @param orderFeatures modify feature run order within a specification (yes/no)? + * @param ascending sort in ascending order (yes/no)? + */ public AlphabeticalSpecOrderer(boolean orderSpecs, boolean orderFeatures, boolean ascending) { super(orderSpecs, orderFeatures); this.ascending = ascending; } + /** + * Create an alphabetical spec orderer with a default ascending sort order + * + * @param orderSpecs modify specification run order (yes/no)? + * @param orderFeatures modify feature run order within a specification (yes/no)? + * @see #AlphabeticalSpecOrderer(boolean, boolean, boolean) + */ public AlphabeticalSpecOrderer(boolean orderSpecs, boolean orderFeatures) { this(orderSpecs, orderFeatures, true); } + /** + * Create an alphabetical spec orderer with default values. This is a shorthand for calling + * {@link #AlphabeticalSpecOrderer(boolean, boolean, boolean)} with parameters {@code true, true, true}. + */ public AlphabeticalSpecOrderer() { this(true, true); } diff --git a/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/AnnotatationBasedSpecOrderer.java b/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/AnnotatationBasedSpecOrderer.java index 953ee1973b..3dcf58baed 100644 --- a/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/AnnotatationBasedSpecOrderer.java +++ b/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/AnnotatationBasedSpecOrderer.java @@ -6,7 +6,15 @@ import java.util.Collection; +/** + * Spec orderer for usef-defined, manual specification and/or feature method ordering, to be used in connection with + * {@link Order @Order} annotations. See the Spock user manual for more details. + */ public class AnnotatationBasedSpecOrderer extends SpecOrderer { + /** + * Create an annotation-based spec orderer + * @see Order + */ public AnnotatationBasedSpecOrderer() { super(true, true); } diff --git a/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/DefaultSpecOrderer.java b/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/DefaultSpecOrderer.java index b1efc71d51..8b08a40a1a 100644 --- a/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/DefaultSpecOrderer.java +++ b/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/DefaultSpecOrderer.java @@ -5,7 +5,13 @@ import java.util.Collection; +/** + * No-op spec orderer, used as a default if no other orderer is configured + */ public class DefaultSpecOrderer extends SpecOrderer { + /** + * Create a no-op spec orderer + */ public DefaultSpecOrderer() { super(false, false); } diff --git a/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/RandomSpecOrderer.java b/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/RandomSpecOrderer.java index 5774c06107..08e32df1f7 100644 --- a/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/RandomSpecOrderer.java +++ b/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/RandomSpecOrderer.java @@ -6,18 +6,42 @@ import java.util.Collection; import java.util.Random; +/** + * Orderer capable of randomizing specification and/or feature method run order + */ public class RandomSpecOrderer extends SpecOrderer { private final Random random; + /** + * Create a random spec orderer + * + * @param orderSpecs modify specification run order (yes/no)? + * @param orderFeatures modify feature run order within a specification (yes/no)? + * @param seed random seed to be used in {@link Random#Random(long)}; setting this to a fixed value enables + * you to create test runs with repeatable pseudo-random run ordering, which can be helpful when + * e.g. debugging tests failing due to a particular run order, making them more independent of + * each other in the process + */ public RandomSpecOrderer(boolean orderSpecs, boolean orderFeatures, long seed) { super(orderSpecs, orderFeatures); random = new Random(seed); } + /** + * Create a random spec orderer with a default random seed of {@code System.currentTimeMillis()} + * + * @param orderSpecs modify specification run order (yes/no)? + * @param orderFeatures modify feature run order within a specification (yes/no)? + * @see #RandomSpecOrderer(boolean, boolean, long) + */ public RandomSpecOrderer(boolean orderSpecs, boolean orderFeatures) { this(orderSpecs, orderFeatures, System.currentTimeMillis()); } + /** + * Create a random spec orderer with default values. This is a shorthand for calling + * {@link #RandomSpecOrderer(boolean, boolean, long)} with parameters {@code true, true, System.currentTimeMillis()}. + */ public RandomSpecOrderer() { this(true, true); } diff --git a/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/SpecOrderer.java b/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/SpecOrderer.java index 13e33c5540..e26b42f124 100644 --- a/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/SpecOrderer.java +++ b/spock-core/src/main/java/org/spockframework/runtime/extension/builtin/orderer/SpecOrderer.java @@ -1,19 +1,40 @@ package org.spockframework.runtime.extension.builtin.orderer; import org.spockframework.runtime.SpecProcessor; +import org.spockframework.runtime.model.FeatureInfo; import org.spockframework.runtime.model.SpecInfo; import java.util.Collection; +/** + * Abstract base class for specification and feature method orderers, i.e. workers modifying the corresponding execution + * order properties of spec-info and feature-info instances. + * + * @see DefaultSpecOrderer + * @see RandomSpecOrderer + * @see AnnotatationBasedSpecOrderer + * @see AlphabeticalSpecOrderer + */ public abstract class SpecOrderer implements SpecProcessor { protected final boolean orderSpecs; protected final boolean orderFeatures; + /** + * Create a spec-orderer with a user-defined operational scope + * + * @param orderSpecs modify specification run order (yes/no)? + * @param orderFeatures modify feature run order within a specification (yes/no)? + */ public SpecOrderer(boolean orderSpecs, boolean orderFeatures) { this.orderSpecs = orderSpecs; this.orderFeatures = orderFeatures; } + /** + * Dispatch to {@link #orderSpecs(Collection)} and then to {@link #orderFeatures(Collection)} for each spec-info + * + * @param specs spec-info instances to be processed + */ @Override public void process(Collection specs) { if (orderSpecs) @@ -24,8 +45,43 @@ public void process(Collection specs) { orderFeatures(spec.getAllFeatures()); } + /** + * Assign values to specification run orders. Implementors are expected to modify the corresponding object state + * in place, e.g. like this: + *
+   * for (SpecInfo spec : specs)
+   *   spec.setExecutionOrder(random.nextInt());
+   * 
+ * Or maybe: + *
+   * AtomicInteger i = new AtomicInteger();
+   * specs.stream()
+   *   .sorted(myComparator)
+   *   .forEach(specInfo -> specInfo.setExecutionOrder(i.getAndIncrement()));
+   * 
+ * + * @param specs spec-info instances to be ordered + */ + protected abstract void orderSpecs(Collection specs); + /** + * Assign values to feature run orders. Implementors are expected to modify the corresponding object state + * in place, e.g. like this: + *
+   * for (FeatureInfo feature : features)
+   *   feature.setExecutionOrder(random.nextInt());
+   * 
+ * Or maybe: + *
+   * AtomicInteger i = new AtomicInteger();
+   * features.stream()
+   *   .sorted(myComparator)
+   *   .forEach(featureInfo -> featureInfo.setExecutionOrder(i.getAndIncrement()));
+   * 
+ * + * @param features feature-info instances to be ordered + */ protected abstract void orderFeatures(Collection features); public boolean isOrderSpecs() { diff --git a/spock-core/src/main/java/spock/lang/Order.java b/spock-core/src/main/java/spock/lang/Order.java index 46af7265c5..39341e8467 100644 --- a/spock-core/src/main/java/spock/lang/Order.java +++ b/spock-core/src/main/java/spock/lang/Order.java @@ -30,6 +30,8 @@ * runner { * orderer new AnnotatationBasedSpecOrderer() * } + *

+ * See the Spock user manual for more details. */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD })