11

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?

fedor.belov
  • 22,343
  • 26
  • 89
  • 134

5 Answers5

16

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.

Tomasz Kalkosiński
  • 3,673
  • 1
  • 19
  • 25
  • 1. It forces me to use expect/where construction – fedor.belov Jun 06 '12 at 08:47
  • 2. I also need to repeat tests where expect/where construction is used to test purposes – fedor.belov Jun 06 '12 at 08:48
  • 1
    @fedor.belov you can use given/when/then/were construction too. Can you edit your question and write an example test that you would write with Repeat annotation if it would work? – Tomasz Kalkosiński Jun 06 '12 at 09:23
  • Tomasz Kalkosiński, thank you, I didn't now about it because I'm new to spock framework. I still don't know how to repeat tests with expect/where construction – fedor.belov Jun 06 '12 at 10:50
  • @fedor.belov your `x` serves as argument for `getResult(x)` and as a test counter? I suppose your test construction is not right. Why do you want to repeat test x times? Even if `@Repeat` would work you still cannot achieve what you want. `@Repeat` needs integer as an argument. – Tomasz Kalkosiński Jun 06 '12 at 11:09
  • It's coincidence. `x` servers only as argument for `getResult(x)`. It doesn't corresponds to test repeats count – fedor.belov Jun 06 '12 at 11:35
1

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.

Peter Niederwieser
  • 121,412
  • 21
  • 324
  • 259
0

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();
        }
    }
}
fedor.belov
  • 22,343
  • 26
  • 89
  • 134
  • This may not give the correct results. Among other things, it will use the same spec instance for all repetitions. `invocation.proceed()` isn't currently designed to be called multiple times. – Peter Niederwieser Jun 13 '12 at 00:46
0

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]
}
Saikat
  • 14,222
  • 20
  • 104
  • 125
Sanjay Bharwani
  • 3,317
  • 34
  • 31
0

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;
}