Spock - 运行数据表计数

Man*_*nie 2 groovy spock

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
    }
}
Run Code Online (Sandbox Code Playgroud)

kri*_*aex 5

这真的很难看,因为它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
  }
}
Run Code Online (Sandbox Code Playgroud)

控制台日志:

1
2
3
Run Code Online (Sandbox Code Playgroud)

请注意,这仅适用于@Unrolled 功能方法,而不适用于没有该注释的方法。


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

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

您可能知道主要是注释驱动的内置 Spock 扩展,例如@Ignore, @Timeout, @Stepwise, @Issue, @AutoCleanup。但是也有手册中没有描述但仍然存在的全局扩展,例如ReportLogExtensionIncludeExcludeExtension

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

全球 Spock 扩展:

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

1
2
3
Run Code Online (Sandbox Code Playgroud)

每个扩展都需要注册。因此,请同时将META-INF/services/org.spockframework.runtime.extension.IGlobalExtension包含以下内容的文件添加到您的测试资源中:

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++
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

展柜规格:

de.scrum_master.app.IterationCountExtension
Run Code Online (Sandbox Code Playgroud)

控制台日志:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,无论是否@Unroll使用该扩展程序都可以正常工作。在这方面,它也比上面的快速和肮脏的解决方案更好。

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