Spock - 运行 数据 table 计数

Spock - running data table count

Spock 中是否有任何方法可以在使用数据表时透明地获取当前 运行 计数,而无需将其作为显式输入参数?

例如

class MathSpec extends Specification {
    def "maximum of two numbers"(int a, int b, int c) {
        expect:
        Math.max(a, b) == c
        println "this is row:" + $currentRowCount//??


        where:
        a | b | c
        1 | 3 | 3
        7 | 4 | 4
        0 | 0 | 0
    }
}

您可以将 @Unroll#iterationCount 一起使用,即:

import spock.lang.*

class MathSpec extends Specification {

    @Unroll
    def "maximum of #a and #b is #c (iteration #iterationCount)"() {
        given:
        def result = Math.max(a, b)

        expect:
        result == c

        where:
        a | b | c
        1 | 3 | 3
        7 | 4 | 4
        0 | 0 | 0
    }
}

PS: 不要调用你的 class Math,然后尝试调用 Math.max ;-)

这真的很难看,因为iterationCount是一个私有变量,但是可能:

规范示例:

package de.scrum_master.app

import spock.lang.Specification
import spock.lang.Unroll

class PieceTest extends Specification {
  @Unroll
  def "do something with data table item #item"() {
    expect:
    println specificationContext
      .currentIteration
      .parent
      .iterationNameProvider
      .iterationCount

    where:
    item  | anotherItem
    "foo" | 333
    "bar" | 444
    "zot" | 555
  }
}

控制台日志:

1
2
3

请注意,这仅适用于 @Unrolled 特征方法,在没有该注释的情况下无效。


更新:通过全局 Spock 扩展公开迭代计数

免责声明:我喜欢 Spock,但我不擅长 Groovy 元编程。这也是我的第一个 Spock 扩展。

你可能知道built-in Spock extensions,其中大部分是annotation-driven,例如@Ignore@Timeout@Stepwise@Issue@AutoCleanup。但是也有手册中没有描述但仍然存在的全局扩展,例如ReportLogExtension, IncludeExcludeExtension.

不幸的是,手册没有描述如何创建这样的扩展,但通过一些谷歌搜索和源代码研究,您可以找到答案。不过,这对初学者来说没什么。

全球 Spock 扩展:

此扩展为每个 Spock 规范添加了一个动态成员 iterationCount

package de.scrum_master.app

import org.spockframework.runtime.AbstractRunListener
import org.spockframework.runtime.extension.AbstractGlobalExtension
import org.spockframework.runtime.model.FeatureInfo
import org.spockframework.runtime.model.IterationInfo
import org.spockframework.runtime.model.SpecInfo

class IterationCountExtension extends AbstractGlobalExtension {
  @Override
  void visitSpec(SpecInfo spec) {
    spec.addListener(new IterationCountListener())
  }

  static class IterationCountListener extends AbstractRunListener {
    MetaClass metaClass
    int iterationCount

    @Override
    void beforeSpec(SpecInfo spec) {
      println spec.name
      metaClass = spec.reflection.metaClass
    }

    @Override
    void beforeFeature(FeatureInfo feature) {
      println "  " + feature.name
      iterationCount = 0
      metaClass.iterationCount = iterationCount
    }

    @Override
    void beforeIteration(IterationInfo iteration) {
      println "    " + iteration.name
      metaClass.iterationCount = iterationCount++
    }
  }
}

每个分机都需要注册。所以也请在您的测试资源中添加一个包含以下内容的文件META-INF/services/org.spockframework.runtime.extension.IGlobalExtension

de.scrum_master.app.IterationCountExtension

展柜规格:

package de.scrum_master.app

import spock.lang.Specification
import spock.lang.Unroll

class SampleTest extends Specification {
  def "no data table"() {
    expect:
    println "      " + iterationCount
  }

  def "data table items"() {
    expect:
    println "      " + iterationCount

    where:
    item  | anotherItem
    "foo" | 333
    "bar" | 444
    "zot" | 555
  }

  @Unroll
  def "unrolled data table item"() {
    expect:
    println "      " + iterationCount

    where:
    item  | anotherItem
    "foo" | 333
    "bar" | 444
    "zot" | 555
  }

  @Unroll
  def "unrolled data table item #item"() {
    expect:
    println "      " + iterationCount

    where:
    item  | anotherItem
    "foo" | 333
    "bar" | 444
    "zot" | 555
  }
}

控制台日志:

SampleTest
  no data table
    no data table
      0
  data table items
    data table items
      0
    data table items
      1
    data table items
      2
  unrolled data table item
    unrolled data table item[0]
      0
    unrolled data table item[1]
      1
    unrolled data table item[2]
      2
  unrolled data table item #item
    unrolled data table item foo
      0
    unrolled data table item bar
      1
    unrolled data table item zot
      2

如您所见,无论是否使用 @Unroll,扩展都有效。在这方面,它也比上面的快速和肮脏的解决方案更好。

顺便说一句,如果您希望计数从 1 开始而不是从 0 开始,只需在扩展侦听器方法 beforeIteration 中将表达式 iterationCount++ 切换为 ++iterationCount

只是为了更新这个答案。在 spock 版本 2.1-groovy-3.0 上验证以获取行号使用:

  specificationContext.currentIteration.iterationIndex

一个