Ubeogesh
Ubeogesh

Reputation: 1870

In Spock framework, how do I access data table variable from "error" listener?

I have a test with a data table, e.g. like this:

@Unroll
"Basic session start on platform = #platform"() {
    when: "user stats a session on a platform"
    def response = startSession(platform, id) // it does a REST request

    then: "response contains a userId"
    assert verifyUserId(response.userId) // method verifies userId with an internal algorithm and returns true\false if it is valid or not

    where:
    id | platform
    1  | "Facebook"
    2  | "Google"
    3  | "Apple"
}

I have also wrote a listener for errors.

class MyListener extends AbstractListener {
...
   public void error(ErrorInfo error) { ... }
...
}

So that in case an assertion error happens during test execution, the code goes into this "error" method.

The question is, how can I get values of variables from the "where" block from inside the "error" method?

I don't do direct assertions for the data table variables, so ErrorInfo.Exception does not contain them.

I also could not find any other suitable members of the "ErrorInfo" object - I can only find variable names in ErrorInfo.getMethod().getFeature(), but not their values that were there when the error happened.

Upvotes: 2

Views: 1232

Answers (1)

Ivan Lymar
Ivan Lymar

Reputation: 2293

The main issue here is that ErrorInfo doesn't provide current spec instance, that's why you can't get iteration variables. So I would suggest two ways:

First one is to use iteration interceptor:

class ListenForErrorsExtension implements IGlobalExtension {

    void visitSpec(SpecInfo specInfo) {
        specInfo.addListener(new Listener())
        specInfo.allFeatures*.addIterationInterceptor(new IMethodInterceptor() {                      
            @Override
            void intercept(IMethodInvocation invocation) {
                holder.put(invocation.iteration.dataValues)
                invocation.proceed()
            }

        })
    }

The second one was kindly suggested in comments by Opal. You could instantinate not AbstractRunListener, but IRunListener

class ErrorExtension implements IGlobalExtension{
....
    @Override
    void beforeIteration(IterationInfo iteration) {       
        holder.put(iteration.dataValues)
    }
....
}

It gives you access to each iterration, but the main idea is still following:

You have to create thread safe holder, put iterration data to it BEFORE error happened and then extract.

Upvotes: 1

Related Questions