使用Spock在不同的测试环境中运行测试

时间:2018-05-17 03:16:58

标签: testing spock test-environments

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

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

     }
 }

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

{{1}}

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

2 个答案:

答案 0 :(得分:0)

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

<div class="row">
<div class="col-sm-12">
<input app-vast-url-validate="" type="url" class="input-full-width ng-valid-required ng-valid-vast-url ng-dirty ng-touched ng-valid ng-valid-url" id="callback_url_0" name="callback_url_0" ng-model="callback.url" placeholder="Enter Callback URL" ng-keyup="onAddCallbackFormControl($event, callback)" required="" style="">
</div>
</div>

在此示例中,我们准备共享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

属性(或者您可以使用env变量传递相同的信息)。在这个例子中,如果缺少给定属性,我们也使用默认值 - 在这种情况下-Dexecution.environment=value (如果忘记指定执行环境变量,它将阻止测试失败)。

替代方案:test条件执行

Spock支持条件执行。如果我们使用@IgnoreIf方法,请查看相同的测试结果:

@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

我猜你看到它开始有多大问题。

答案 1 :(得分:0)

Spock有Multi-Variable Data Pipes来处理这件事。您可以将“逻辑”移动到数据驱动的方法。

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()中的两个不同的班级MathProductionSpecMathStagingSpec实施 我会根据你的环境使用spock annotations来执行。

示例:

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] ]
    }
}