The easiest way that comes to my mind to achieve your expectation is to prepare the data before running test methods based on some condition (e.g. execution environment) and then use this predefined data in your tests. Consider following example:
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
}
}
In this example we prepare shared data
that holds values we will use in tests. Here we are expecting that the execution environment information will be passed as
-Dexecution.environment=value
property (alternatively you can pass the same information using env variables). In this example we also use the default value if given property is missing - test
in this case (it will prevent test from failing if you forgot specifying your execution environment variable).
Alternative: @IgnoreIf
conditional exection
Spock supports conditional execution. Take a look what the same test would look like if we use @IgnoreIf
approach:
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
}
}
Unfortunately, this approach requires a lot of duplication: you have to duplicate test methods and you can't re-use the same name (compiler does not allow to do that). It's pretty error-prone - you have to pay attention to put the same test body to all methods that should test the same stuff, but with different data. Another thing is that condition passed to @IgnoreIf
will have to be modified if you introduce 3rd environment - in this case you will specify it something like that:
@IgnoreIf({ !(System.getProperty('execution.environment') in ['staging', 'prod']) })
I guess you see how much problematic it starts to be.