Groovy 在Spock框架中,如何从;“错误”;听众?

Groovy 在Spock框架中,如何从;“错误”;听众?,groovy,listener,spock,data-driven-tests,Groovy,Listener,Spock,Data Driven Tests,我有一个数据表测试,例如: @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 verifyUs

我有一个数据表测试,例如:

@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"
}
我还为错误编写了一个侦听器

class MyListener extends AbstractListener {
...
   public void error(ErrorInfo error) { ... }
...
}
因此,如果在测试执行期间发生断言错误,代码将进入这个“错误”方法

问题是,如何从“error”方法内部的“where”块中获取变量值

我不直接断言数据表变量,所以ErrorInfo.Exception不包含它们


我也找不到“ErrorInfo”对象的任何其他合适成员-我只能在ErrorInfo.getMethod().getFeature()中找到变量名,但找不到发生错误时存在的变量值。

这里的主要问题是ErrorInfo不提供当前规范实例,这就是为什么无法获取迭代变量。因此,我建议两种方法:

第一个是使用迭代拦截器:

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()
            }

        })
    }
第二个建议是欧泊在评论中提出的。您可以实例化的不是
AbstractRunListener
,而是
IRunListener

class ErrorExtension implements IGlobalExtension{
....
    @Override
    void beforeIteration(IterationInfo iteration) {       
        holder.put(iteration.dataValues)
    }
....
}
它使您可以访问每个iterration,但主要思想如下:


您必须创建线程安全夹,在错误发生之前将iterration数据放入其中,然后提取。

您能提供完整的示例规范吗?我提供了功能方法的完整示例-这就是您的意思吗?规范只是将其包装在一个类中,在我的情况下,它甚至没有任何设置\清理。(点击它-链接在那里)工作,但不知道它是否是你正在寻找的,如果它是线程安全的-试试看。谢谢!我使用了迭代拦截器。我在监听器中创建了一个对象变量,并在intercept方法中为其赋值(dataValues),然后在“error”中使用它。据我所知(顺便说一句,我完全不需要线程安全保护器),因为侦听器是根据规范创建的,在我们的例子中,规范在一个线程中运行。@Ubeogesh希望这会有所帮助:顺便说一句,这总是要视情况而定,但通常人们会通过在多个线程中运行它来减少测试回归时间。这就是我建议线程安全的原因。我们确实在多个线程中运行测试-但是它们是由规范并行的(每个规范都有自己的侦听器\迭代侦听器)