Spock:数据管道和变量分配

Spock: Data Pipes, and Variable Assignments

来自 Spock documentation:

Data tables, data pipes, and variable assignments can be combined as needed:

...
where:
a | _
3 | _
7 | _
0 | _

b << [5, 0, 0]

c = a > b ? a : b

这个简单的示例为 y 生成 MissingPropertyException

def test() {
    expect:
        x == 42
    where:
        y = 12
        x << [y + 30, 54 - y]
}

这个例子有什么问题?

我认为赋值 y=12 在 where 块中是不允许的。 例如,这个版本有效,两个测试 运行 符合预期:

class SampleTest extends Specification {
 @Unroll
 def "test"() {
    expect:
    x == 42
    where:
    x << [12 + 30, 54 - 12]
 }
}

如果您绝对需要作业,以下方法也适用:

class SampleTest extends Specification {
 @Unroll
 def "test"() {
    expect:
    x == 42
    where:
    x << myfunc()
 }

 def myfunc() {
    def y = 12
    [y + 30, 54 - y]
 }
}

你不能那样混合数据管道和变量赋值。让我们看一下源代码。您可以在第 49 行的 org.spockframework.runtime.ParameterizedSpecRunner class 中放置一个断点,并使用调试器进行测试 运行。您会看到 currentFeature 包含两个名称为 yx 的参数:

您还会注意到变量名 x 定义了一个 dataProvider

此数据提供程序存在是因为我们已将 x 定义为数据管道,因此它必须遍历变量列表并在数据管道的上下文中对其进行评估。在此上下文中,它期望 y 变量也被定义为数据管道,因此它可以采用与同一索引关联的值。

如果您将 where: 定义为:

where:
y << [12, 12]
x << [y + 30, 54 - y]

您的测试会成功,因为现在 y 变量作为数据提供者存在,并且 x 的评估值使用第二个数据提供者访问 y 的值。

如何将变量赋值与数据管道相结合?

考虑以下示例:

@Unroll
def "variable assignment example"() {
    expect:
    x == 42

    and:
    c

    where:
    y <<  [12, 12]
    x << [y + 30, 54 - y]
    c = y < x
}

在这种情况下,变量 c 为数据管道 yx 中的每个元素计算两次。当第一次展开发生时 y = 12x = y + 30 => 12 + 30 => 42c 的计算结果为 true,因为 y<x。当第二次展开发生时,12 值再次分配给 yx 计算为 4254 - y => 54 - 12 => 42),c 计算为 true 再次。

结论

我看到它可能看起来很简单 y = 12 变量赋值应该由数据管道评估发现。不幸的是,它不是那样工作的。评估数据管道时,它只能使用来自其他数据管道的值,并且在此上下文中看不到任何变量赋值。