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)
这真的很难看,因为它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。但是也有手册中没有描述但仍然存在的全局扩展,例如ReportLogExtension,IncludeExcludeExtension。
不幸的是,手册没有描述如何创建这样的扩展,但是通过一些谷歌搜索和源代码研究,你可以找到。不过,对于初学者来说,这没什么。
全球 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。