Spock:可重用的数据表

时间:2017-10-10 13:03:50

标签: groovy spock

我可以进行这样的测试并将where子句数据表提取到可重用的块中吗?

@Unroll
void "test that doSomething with #a and #b does not fail"(String a, String b) {
    when:
        doSomethingWithAandB(a, b)
    then:
        notThrown(Exception)
    where:
        a     | b
        "foo" | "bar"
        "foo" | "baz"
        "foo" | "foo"
}
像这样的东西(伪代码):

@Unroll
void "test that doSomethingElse with #a and #b does not fail"(String a, String b) {
    when:
        doSomethingElseWithAandB(a, b)
    then:
        notThrown(Exception)
    where:
        dataTable()
}

def dataTable(a, b) {  // this is now reusable in multiple tests
        a     | b
        "foo" | "bar"
        "foo" | "baz"
        "foo" | "foo"        
}

3 个答案:

答案 0 :(得分:3)

where子句中的表格式数据实际上在编译时被解析为一组OR表达式,被收集到列表列表中然后进行转置,所以这个:

where:
a | b | c
1 | 0 | 1
2 | 2 | 2
4 | 5 | 5

将转变为:

where:
a << [1, 2, 4]
b << [0, 2, 5]
c << [1, 2, 5]
在生成测试方法之前

(有关详细信息,请参阅org.spockframework.compiler.WhereBlockRewriter)。此var << list构造在documentation中称为“数据管道”。

升级现有的答案,从Spock 1.1开始,人们可以使用名为“多变量数据管道”的构造稍微缩短代码,该构造将转置表格:

class SampleTest extends Specification {
    @Unroll
    def "max of #a and #b gives #c"() {
        expect:
        Math.max(a, b) == c
        where:
        [a, b, c] << dataTable()
    }

    static def dataTable() {
        [
                [1, 0, 1],
                [2, 2, 2],
                [4, 5, 5]
        ]
    }
}

有趣的事实:虽然docs on Syntactic Variations没有解释原因,但是因为表行被解析为一组OR表达式,所以也可以使用双栏 -

where:
a | b || c
1 | 0 || 1
2 | 2 || 2
4 | 5 || 5

答案 1 :(得分:2)

是的,你可以。

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

class SampleTest extends Specification {
  @Unroll
  def "max of #a and #b gives #c"() {
  expect:
    Math.max(a, b) == c
  where:
    a << aProvider()
    b << bProvider()
    c << cProvider()
 }

 private List<Integer> aProvider() {
   [1 ,2 ,4]
 }
 private List<Integer> bProvider() {
   [0 ,2 ,5]
 }

 private List<Integer> cProvider() {
    [1 ,2 ,5]
 }
}

当然,aProvider / bProvider / cProvider可以以“更加通用的方式”重写,除其他外,可以外部化到某个类并在许多测试中重用。您不必指定表,但可以提供“数据管道”。在Data Driven Testing章节中阅读更多内容。

答案 2 :(得分:0)

谢谢Mark,为你的answer!根据我所学到的,我已经找到了一个相当简单的解决方案。

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

class SampleTest extends Specification {
    @Unroll
    def "max of #a and #b gives #c"() {
        expect:
            Math.max(a, b) == c
        where:
            params << dataTable()
            a = params.a
            b = params.b
            c = params.c
    }

    // this is now reusable in multiple tests
    def dataTable() {
        return [
            // case 1
            [
                a: 1,
                b: 0,
                c: 1
            ],

            // case 2
            [
                a: 1,
                b: 2,
                c: 2
            ],

            // case 3
            [
                a: 4,
                b: 5,
                c: 5
            ]
        ]
    }
}