Skip to content

Commit

Permalink
Fix too many arguments set as data values in iteration info (#1690)
Browse files Browse the repository at this point in the history
The iteration info holds a list of the data values for the current iteration.
The data driver logic had an error where it gave all parameter infos
to the data driver instead of only the ones representing data variables.
Data drivers only deal with data variables, not with additional arguments that
are supplied by extensions. Due to that the data values in the iteration info
had additional MISSING_ARGUMENT entries for the additional arguments which
then also broke things like unroll patterns, conditional annotations accessing data
values and so on
  • Loading branch information
Vampire authored Oct 11, 2023
1 parent 55503c3 commit 03b1d6c
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void runParameterizedFeature(SpockExecutionContext context, ParameterizedFeature
try (IDataIterator dataIterator = new DataIteratorFactory(supervisor).createFeatureDataIterator(context)) {
IIterationRunner iterationRunner = createIterationRunner(context, childExecutor);
IDataDriver dataDriver = feature.getDataDriver();
dataDriver.runIterations(dataIterator, iterationRunner, feature.getFeatureMethod().getParameters());
dataDriver.runIterations(dataIterator, iterationRunner, feature.getFeatureMethod().getParameters().subList(0, feature.getDataVariables().size()));
childExecutor.awaitFinished();
} catch (InterruptedException ie) {
throw ie;
Expand All @@ -58,9 +58,9 @@ private IIterationRunner createIterationRunner(SpockExecutionContext context, Pa
private final AtomicInteger iterationIndex = new AtomicInteger(0);

@Override
public CompletableFuture<ExecutionResult> runIteration(Object[] args, int estimatedNumIterations) {
public CompletableFuture<ExecutionResult> runIteration(Object[] dataValues, int estimatedNumIterations) {
int currIterationIndex = iterationIndex.getAndIncrement();
IterationInfo iterationInfo = createIterationInfo(context, currIterationIndex, args, estimatedNumIterations);
IterationInfo iterationInfo = createIterationInfo(context, currIterationIndex, dataValues, estimatedNumIterations);
IterationNode iterationNode = new IterationNode(
context.getParentId().append("iteration", String.valueOf(currIterationIndex)),
context.getRunContext().getConfiguration(RunnerConfiguration.class), iterationInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ public interface IDataDriver {
*
* @param dataIterator the data iterator giving access to the data from the data providers. The data iterator is not to be closed by this method.
* @param iterationRunner the iteration runner that will be used to run the test method for each iteration.
* @param parameters the parameters of the test method
* @param parameters the parameters of the test method representing data variables
*/
void runIterations(IDataIterator dataIterator, IIterationRunner iterationRunner, List<ParameterInfo> parameters);

/**
* Prepares the arguments for invocation of the test method.
* Prepares the arguments for the data variables for invocation of the test method.
* <p>
* It is possible to have fewer arguments produced by the data driver than the number of parameters.
* It is possible to have fewer arguments produced by the data driver than the number of data variables.
* In this case, the missing arguments are filled with {@link MethodInfo#MISSING_ARGUMENT}.
* <p>
* Custom implementations of IDataDriver should use this method to prepare the argument array.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ public void runIterations(IDataIterator dataIterator, IIterationRunner iteration
List<Object[]> data = new ArrayList<>(estimatedNumIterations);
dataIterator.forEachRemaining(data::add);
for (int attempt = 0; attempt < maxAttempts; attempt++) {
for (Object[] args : data) {
for (Object[] dataValues : data) {
try {
ExecutionResult executionResult = iterationRunner.runIteration(args, maxIterations).get();
ExecutionResult executionResult = iterationRunner.runIteration(dataValues, maxIterations).get();
if (executionResult == ExecutionResult.FAILED) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import org.spockframework.EmbeddedSpecification
import org.spockframework.runtime.SpockExecutionException
import org.spockframework.runtime.extension.ExtensionAnnotation
import org.spockframework.runtime.extension.IAnnotationDrivenExtension
import org.spockframework.runtime.model.FeatureInfo
import org.spockframework.runtime.model.MethodInfo
import org.spockframework.runtime.model.MethodKind
import spock.lang.Issue
import spock.lang.Rollup
import spock.lang.Unroll
Expand Down Expand Up @@ -256,6 +256,28 @@ def foo() {
]
}

@Foo
def "method arguments in data driven feature methods can be provided by extensions"(a) {
expect:
x == 1
y == 2
a == 'foo'

where:
x = 1
y = 2
}

@Foo
def "additional method arguments do not influence data values in iteration info"(a) {
expect:
specificationContext.currentIteration.dataValues == [1, 2]

where:
x = 1
y = 2
}

static class FooExtension implements IAnnotationDrivenExtension<Foo> {
@Override
void visitFixtureAnnotation(Foo annotation, MethodInfo fixtureMethod) {
Expand All @@ -266,6 +288,16 @@ def foo() {
it.proceed()
}
}

@Override
void visitFeatureAnnotation(Foo annotation, FeatureInfo feature) {
feature.featureMethod.addInterceptor {
assert it.arguments.size() == 3
assert it.arguments[2] == MISSING_ARGUMENT
it.arguments[2] = 'foo'
it.proceed()
}
}
}
}

Expand Down

0 comments on commit 03b1d6c

Please sign in to comment.