fedor.belov
fedor.belov

Reputation: 23323

How can I repeat Spock test?

As described here @Repeat annotation is not supported right now. How can I mark spock test as repeated n times?

Suppose I have spock test:

def "testing somthing"() {
    expect:
    assert myService.getResult(x) == y

    where:
    x | y
    5 | 7
    10 | 12
}

How can I mark it to repeat n times?

Upvotes: 12

Views: 10297

Answers (6)

Sergey Tsypanov
Sergey Tsypanov

Reputation: 4370

In 2024 you can annotate your test with @spock.lang.RepeatUntilFailure and after launch it will be invoked repeatedly.

Upvotes: 0

Sanjay Bharwani
Sanjay Bharwani

Reputation: 4759

Use below code snippet to iterate Spock test for a set of values

def "testing somthing"() {
    expect:
    assert myService.getResult(x) == y

    where:
    x >> [3,5,7]
    y >> [5,10,12]
}

Upvotes: 0

rufflepuss
rufflepuss

Reputation: 1

I have found a somewhat simple way of hacking this together. Spock allows you to pipe the return of a method into the variables defined in the where clause, so using this you can define a method that simply loops over your data multiple times and then returns the combined list.

def "testing somthing"() {
    expect:
    assert myService.getResult(x) == y

    where:
    [x,y] << getMap()
}


public  ArrayList<Integer[]> getMap(){
    ArrayList<Integer[]> toReturn = new ArrayList<Integer[]>();
    for(int i = 0; i < 5; i ++){
        toReturn.add({5, 7})
        toReturn.add({10, 12})
    }
    return toReturn;
}

Upvotes: 0

fedor.belov
fedor.belov

Reputation: 23323

I have found working solution here (ru)

import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.ElementType
import java.lang.annotation.Target
import org.spockframework.runtime.extension.ExtensionAnnotation
import org.spockframework.runtime.extension.AbstractAnnotationDrivenExtension
import org.spockframework.runtime.model.FeatureInfo
import org.spockframework.runtime.extension.AbstractMethodInterceptor
import org.spockframework.runtime.extension.IMethodInvocation

@Retention(RetentionPolicy.RUNTIME)
@Target([ElementType.METHOD, ElementType.TYPE])
@ExtensionAnnotation(RepeatExtension.class)
public @interface Repeat {
    int value() default 1;
}

public class RepeatExtension extends AbstractAnnotationDrivenExtension<Repeat> {

    @Override
    public void visitFeatureAnnotation(Repeat annotation, FeatureInfo feature) {
        feature.addInterceptor(new RepeatInterceptor(annotation.value()));
    }
}

private class RepeatInterceptor extends AbstractMethodInterceptor{
    private final int count;

    public RepeatInterceptor(int count) {
        this.count = count;
    }

    @Override
    public void interceptFeatureExecution(IMethodInvocation invocation) throws Throwable {
        for (int i = 0; i < count; i++) {
            invocation.proceed();
        }
    }
}

Upvotes: 0

Tomasz Kalkosiński
Tomasz Kalkosiński

Reputation: 3723

You can use @Unroll annotation like this:

@Unroll("test repeated #i time")
def "test repeated"() {
    expect:
        println i
    where:
        i << (1..10)
}

It will create 10 separate tests for you.

EDIT after you've edited your question, use the simplest way to achieve this:

def "testing somthing"() {
    expect:
        assert myService.getResult(x) == y

    where:
        x | y
        5 | 7
        5 | 7
        5 | 7
        5 | 7
        5 | 7
        10 | 12
        10 | 12
        10 | 12
        10 | 12
        10 | 12

}

This is currently only way to do this in spock.

Upvotes: 16

Peter Niederwieser
Peter Niederwieser

Reputation: 123910

You can use a where-block as shown in the answer above. There is currently no way to repeat a method that already has a where-block.

Upvotes: 1

Related Questions