1

我目前正在使用 REST Client 和 Spock 编写 REST API 测试。我希望能够在不同的测试环境中运行我的测试。我的测试数据因测试环境而异,因此需要在每个环境中使用和指定不同的输入数据。对于下面的示例测试

class MathSpec extends Specification {
    def "maximum of two numbers"() {
        expect:
            Math.max(a, b) == c

       where:
            a | b || c
            1 | 3 || 3
    }
}

我可以为每个环境指定不同的数据表吗?

class MathSpec extends Specification {
    def "maximum of two numbers"() {
         expect:
              Math.max(a, b) == c

         where:
              @TEST 
              a | b || c
              1 | 3 || 3

              @PROD
              a | b || c
              4 | 5 || 6

     }
 }

如果没有,解决这个问题的最佳方法是什么?谢谢。

4

2 回答 2

0

Spock 有多变量数据管道来处理这个问题。您可以将“逻辑”移至数据驱动的方法。

class MathSpec extends Specification {

   def "maximum of two numbers"(int a, int b, int c) {
        expect:
        Math.max(a, b) == c

        where:
        [a, b, c] << getData()
    }

    def getData() {
        if (System.getProperty("Staging"))
            [ [1, 3, 3] ]
       else
            [ [3, 5, 5] ]
   }
}

在您的情况下,我会使用抽象getData()方法。
我将getData()在两个不同的类中实现,MathProductionSpec并根据您的环境MathStagingSpec
使用spock 注释来执行。

例子:

abstract class MathSpec extends Specification {

    def "maximum of two numbers"(int a, int b, int c) {
        expect:
        Math.max(a, b) == c

        where:
        [a, b, c] << getData()
    }

    def abstract getData()
}
@Production
class MathProductionSpec extends MathSpec {
    def getData() {
        [ [4, 2, 4] ]
    }
}
@Staging
class MathStagingSpec extends MathSpec {
    def getData() {
        [ [1, 3, 3] ]
    }
}
于 2018-05-17T14:26:22.777 回答
0

我想到的实现您期望的最简单方法是在基于某些条件(例如执行环境)运行测试方法之前准备数据,然后在测试中使用这些预定义数据。考虑以下示例:

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

class EnvBasedDataSpec extends Specification {
    @Shared
    static Map data = [:]

    def setupSpec() {
        /* If you want to pick variable from env variables, use:
         * System.getenv().getOrDefault('execution.environment', 'test')
         *
         * If you want to provide variable like -Dexecution.environment=test, use:
         * System.getProperty('execution.environment', 'test')
         */
        def executionEnvironment = System.getProperty('execution.environment', 'test')

        switch (executionEnvironment) {
            case 'test':
                data = [a: 1, b: 3, c: 3]
                break
            case 'prod':
                data = [a: 2, b: 4, c: 4]
                break
        }
    }

    @Unroll
    def "maximum of two numbers (#a, #b) == #c"() {
        expect:
        Math.max(a, b) == c

        where:
        a       | b         || c
        data.a  | data.b    || data.c
    }
}

在这个例子中,我们准备了共享data,它包含我们将在测试中使用的值。这里我们期望执行环境信息将作为

-Dexecution.environment=value 

属性(或者您可以使用环境变量传递相同的信息)。在此示例中,如果缺少给定属性,我们还将使用默认值 -test在这种情况下(如果您忘记指定执行环境变量,它将防止测试失败)。

替代方案:@IgnoreIf条件执行

Spock 支持条件执行。看看如果我们使用方法,同样的测试会是什么样@IgnoreIf子:

import spock.lang.IgnoreIf
import spock.lang.Specification

class AlternativeEnvBasedDataSpec extends Specification {

    @IgnoreIf({ System.getProperty('execution.environment') == 'prod' })
    def "maximum of two numbers (test)"() {
        expect:
        Math.max(a, b) == c

        where:
        a  | b  || c
        1  | 3  || 3
    }

    @IgnoreIf({ System.getProperty('execution.environment') == 'test' })
    def "maximum of two numbers (prod)"() {
        expect:
        Math.max(a, b) == c

        where:
        a  | b  || c
        2  | 4  || 4
    }
}

不幸的是,这种方法需要大量重复:您必须重复测试方法并且不能重复使用相同的名称(编译器不允许这样做)。这很容易出错 - 您必须注意将相同的测试主体放在应该测试相同内容但使用不同数据的所有方法中。另一件事是,@IgnoreIf如果您引入第 3 个环境,则必须修改传递给的条件 - 在这种情况下,您将指定如下内容:

@IgnoreIf({ !(System.getProperty('execution.environment') in ['staging', 'prod']) })

我想你看到它开始有多少问题了。

于 2018-05-17T07:25:52.627 回答