How can I repeat Spock test?
Asked Answered
Z

6

12

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?

Zigrang answered 6/6, 2012 at 7:39 Comment(4)
"What's Kiri-kin-tha's First Law of Metaphysics?" :-PCantus
@fedor.belov, why do you want to repeat your tests in a first place?Coppery
tested method has random part so I wanna check it for correctness multiple timesZigrang
@Cantus "Nothing unreal exists." ;)Conjecture
F
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.

Farmelo answered 6/6, 2012 at 11:54 Comment(0)
P
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.

Pegg answered 6/6, 2012 at 7:48 Comment(6)
1. It forces me to use expect/where constructionZigrang
2. I also need to repeat tests where expect/where construction is used to test purposesZigrang
@Zigrang 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?Coppery
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 constructionZigrang
@Zigrang 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.Coppery
It's coincidence. x servers only as argument for getResult(x). It doesn't corresponds to test repeats countZigrang
F
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.

Farmelo answered 6/6, 2012 at 11:54 Comment(0)
Z
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();
        }
    }
}
Zigrang answered 6/6, 2012 at 12:26 Comment(1)
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.Farmelo
F
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]
}
Fret answered 16/7, 2015 at 11:34 Comment(0)
O
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;
}
Overripe answered 28/12, 2016 at 16:24 Comment(0)
S
0

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

Sunstone answered 26/7 at 15:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.