Skip to content

Commit

Permalink
Extend IGlobalExtension lifecylce by 'initSpecs'
Browse files Browse the repository at this point in the history
New lifecycle method initSpecs(Collection<SpecInfo> specs) is called
once, before visiting single specifications later on in `visitSpec`. It
enables global extensions to view all specifications as an ensemble,
e.g. for iterating over them and rearranging their execution order.

Relates to spockframework#1443.
  • Loading branch information
kriegaex committed Apr 16, 2023
1 parent 109dc6a commit e800ba9
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 6 deletions.
8 changes: 6 additions & 2 deletions docs/extensions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -763,13 +763,17 @@ fully-qualified class name in a file `META-INF/services/org.spockframework.runti
class path. As soon as these two conditions are satisfied, the extension is automatically loaded and used when Spock is
running.

`IGlobalExtension` has the following three methods:
`IGlobalExtension` has the following four methods:

`start()`::
This is called once at the very start of the Spock execution.

`initSpecs(Collection<SpecInfo> specs)`::
This is called once, before visiting single specifications later on in `visitSpec`. It enables global extensions to
view all specifications as an ensemble, e.g. for iterating over them and rearranging their execution order.

`visitSpec(SpecInfo spec)`::
This is called once for each specification. In this method you can prepare a specification with your extension magic,
This is called once for each specification. In this method, you can prepare a specification with your extension magic,
like attaching interceptors to various interception points as described in the chapter <<Interceptors>>.

`stop()`::
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package org.spockframework.runtime;

import org.junit.platform.engine.TestDescriptor;
import org.spockframework.runtime.extension.*;
import org.spockframework.runtime.model.*;
import org.spockframework.util.Nullable;
Expand All @@ -30,6 +31,8 @@
*/
@SuppressWarnings("rawtypes")
public class ExtensionRunner {
private static final SpecInfo EMPTY_SPEC = new SpecInfo();

private final SpecInfo spec;
private final IExtensionRegistry extensionRegistry;
private final IConfigurationRegistry configurationRegistry;
Expand All @@ -42,6 +45,20 @@ public ExtensionRunner(SpecInfo spec, IExtensionRegistry extensionRegistry, ICon
this.configurationRegistry = configurationRegistry;
}

public ExtensionRunner(IExtensionRegistry extensionRegistry, IConfigurationRegistry configurationRegistry) {
this(EMPTY_SPEC, extensionRegistry, configurationRegistry);
}

public void initGlobalExtensions(Set<? extends TestDescriptor> testDescriptors) {
List<SpecInfo> specs = testDescriptors.stream()
.filter(testDescriptor -> testDescriptor instanceof SpecNode)
.map(testDescriptor -> ((SpecNode) testDescriptor).getNodeInfo())
.collect(toList());
for (IGlobalExtension extension : extensionRegistry.getGlobalExtensions()) {
extension.initSpecs(specs);
}
}

public void run() {
runGlobalExtensions();
runAnnotationDrivenExtensions();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ public ExtensionRunner createExtensionRunner(SpecInfo spec) {
return new ExtensionRunner(spec, globalExtensionRegistry, globalExtensionRegistry);
}

public ExtensionRunner createExtensionRunner() {
return new ExtensionRunner(globalExtensionRegistry, globalExtensionRegistry);
}

public PlatformParameterizedSpecRunner createSpecRunner(SpecInfo spec) {
return new PlatformParameterizedSpecRunner(
new MasterRunSupervisor(spec, createStackTraceFilter(spec), diffedObjectRenderer));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import org.junit.platform.engine.*;

import java.util.Set;

import static java.util.Comparator.comparingInt;

class SpockEngineDiscoveryPostProcessor {
Expand All @@ -14,7 +16,9 @@ class SpockEngineDiscoveryPostProcessor {
SpockEngineDescriptor postProcessEngineDescriptor(UniqueId uniqueId, RunContext runContext,
SpockEngineDescriptor engineDescriptor) {
SpockEngineDescriptor processedEngineDescriptor = new SpockEngineDescriptor(uniqueId, runContext);
engineDescriptor.getChildren().stream()
Set<? extends TestDescriptor> testDescriptors = engineDescriptor.getChildren();
initSpecNodes(testDescriptors, runContext);
testDescriptors.stream()
.map(child -> processSpecNode(child, runContext))
.sorted(comparingInt(child -> child instanceof SpecNode ? ((SpecNode) child).getNodeInfo().getExecutionOrder() : 0))
.forEach(processedEngineDescriptor::addChild);
Expand Down Expand Up @@ -46,6 +50,10 @@ private UniqueId toUniqueId(UniqueId parentId, FeatureInfo feature) {
return parentId.append("feature", feature.getFeatureMethod().getReflection().getName());
}

private void initSpecNodes(Set<? extends TestDescriptor> testDescriptors, RunContext runContext) {
runContext.createExtensionRunner().initGlobalExtensions(testDescriptors);
}

private TestDescriptor processSpecNode(TestDescriptor child, RunContext runContext) {
if (child instanceof SpecNode) {
SpecNode specNode = (SpecNode) child;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@

import org.spockframework.runtime.model.SpecInfo;

import java.util.Collection;

// TODO: start/stop lifecycle
// TODO: design threading model
public interface IGlobalExtension {
default void start() {};
default void visitSpec(SpecInfo spec){};
default void stop(){};
default void start() {}
default void initSpecs(Collection<SpecInfo> specs) {}
default void visitSpec(SpecInfo spec) {}
default void stop() {}
}

0 comments on commit e800ba9

Please sign in to comment.