Spock - 使用不同的系统默认值重复测试
Spock - repeating tests with different system defaults
我有一个 Spock 规范,用于测试采用 java.util.Date
.
的方法
def "special dates are identified correctly"() {
expect:
isSpecialDay(Date.parse('yyyy/MM/dd', date)) == special
where:
date | special
'2010/01/01' | false
'2011/01/01' | true
'2012/01/01' | true
'2013/01/01' | false
'2014/01/01' | true
// and lots more...
}
我想确保 TimeZone 不会对我的方法实现产生影响(即 2011 年 1 月 1 日是特殊的,无论我处于 EST 还是 GMT 或其他什么)。 有没有一种方法可以在单个 运行 中重复执行测试方法,每次执行时使用不同的默认时区?
我可以将第三列添加到时区的 "where" 块,但额外的维度会使 table 对我来说太大了。
目前,我正在为每个测试设置一个随机默认值 运行,但我不喜欢我的测试不是 repeatable 的事实,并且如果失败,有问题的断言消息中未捕获时区。
@Shared TimeZone defaultTz = TimeZone.getDefault()
def setupSpec() {
def tzIds = TimeZone.getAvailableIDs()
def randomTzId = tzIds[new Random().nextInt(tzIds.length)]
def randomTz = TimeZone.getTimeZone(randomTzId)
println "Using TimeZone $randomTz for test spec"
TimeZone.setDefault(TimeZone.getTimeZone(randomTzId));
}
def cleanupSpec() {
TimeZone.setDefault(defaultTz)
}
使用 JodaTime
您可以使用 DateTimeZone.getAvailableIDs()
测试所有可用时区的相同内容。这是一个快速而令人讨厌的实现,以展示如何完成它。
@Grab(group='joda-time', module='joda-time', version='2.9')
@Grab(group='org.spockframework', module='spock-core', version='1.0-groovy-2.4')
import spock.lang.*
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
class TestSpecialDate extends Specification {
def "special dates are identified correctly"() {
expect:
DateTimeZone.availableIDs.each { tz ->
// get current moment in default time zone
DateTime dt = new DateTime( Date.parse( 'yyyy/MM/dd', date ) )
// translate to local date time
DateTime dtLocal = dt.withZone( DateTimeZone.forID( tz ) )
// Get Java Date and assert
assert isSpecialDay( dtLocal.toDate() ) == special
}
where:
date || special
'2010/01/07' || false
'2011/01/01' || true
'2012/01/01' || true
'2013/11/06' || false
'2014/01/01' || true
}
// Mimic special day implementation
static private boolean isSpecialDay(Date date) {
// Check if it is the first day of month
return date[Calendar.DAY_OF_MONTH] == 1
}
}
这是一个使用我在上面暗示的组合技巧的例子:
@Grab(group='joda-time', module='joda-time', version='2.9')
@Grab(group='org.spockframework', module='spock-core', version='1.0-groovy-2.4')
import spock.lang.*
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
class TestSpecialDate extends Specification {
@Shared def zoneCombinations = [
DateTimeZone.availableIDs,
[[date:'2010/01/07', special:false], [date:'2011/01/01', special:true], [date:'2012/01/01', special:true],
[date:'2013/11/06', special:false], [date:'2014/01/01', special:true]]]
.combinations { a, b -> [zone:a, date:b.date, special:b.special] }
@Unroll
def "#date for #zone should be special #special"() {
expect:
// get current moment in default time zone
DateTime dt = new DateTime( Date.parse( 'yyyy/MM/dd', date ) )
// translate to local date time
DateTime dtLocal = dt.withZone( DateTimeZone.forID( zone ) )
// Get Java Date and assert
isSpecialDay( dtLocal.toDate() ) == special
where:
date << zoneCombinations.date
special << zoneCombinations.special
zone << zoneCombinations.zone
}
// Mimic special day implementation
static private boolean isSpecialDay(Date date) {
// Check if it is the first day of month
return date[Calendar.DAY_OF_MONTH] == 1
}
}
在 groovy 控制台中执行时,运行:
JUnit 4 Runner, Tests: 2915, Failures: 0, Time: 351
2915 次测试:-)
我有一个 Spock 规范,用于测试采用 java.util.Date
.
def "special dates are identified correctly"() {
expect:
isSpecialDay(Date.parse('yyyy/MM/dd', date)) == special
where:
date | special
'2010/01/01' | false
'2011/01/01' | true
'2012/01/01' | true
'2013/01/01' | false
'2014/01/01' | true
// and lots more...
}
我想确保 TimeZone 不会对我的方法实现产生影响(即 2011 年 1 月 1 日是特殊的,无论我处于 EST 还是 GMT 或其他什么)。 有没有一种方法可以在单个 运行 中重复执行测试方法,每次执行时使用不同的默认时区?
我可以将第三列添加到时区的 "where" 块,但额外的维度会使 table 对我来说太大了。
目前,我正在为每个测试设置一个随机默认值 运行,但我不喜欢我的测试不是 repeatable 的事实,并且如果失败,有问题的断言消息中未捕获时区。
@Shared TimeZone defaultTz = TimeZone.getDefault()
def setupSpec() {
def tzIds = TimeZone.getAvailableIDs()
def randomTzId = tzIds[new Random().nextInt(tzIds.length)]
def randomTz = TimeZone.getTimeZone(randomTzId)
println "Using TimeZone $randomTz for test spec"
TimeZone.setDefault(TimeZone.getTimeZone(randomTzId));
}
def cleanupSpec() {
TimeZone.setDefault(defaultTz)
}
使用 JodaTime
您可以使用 DateTimeZone.getAvailableIDs()
测试所有可用时区的相同内容。这是一个快速而令人讨厌的实现,以展示如何完成它。
@Grab(group='joda-time', module='joda-time', version='2.9')
@Grab(group='org.spockframework', module='spock-core', version='1.0-groovy-2.4')
import spock.lang.*
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
class TestSpecialDate extends Specification {
def "special dates are identified correctly"() {
expect:
DateTimeZone.availableIDs.each { tz ->
// get current moment in default time zone
DateTime dt = new DateTime( Date.parse( 'yyyy/MM/dd', date ) )
// translate to local date time
DateTime dtLocal = dt.withZone( DateTimeZone.forID( tz ) )
// Get Java Date and assert
assert isSpecialDay( dtLocal.toDate() ) == special
}
where:
date || special
'2010/01/07' || false
'2011/01/01' || true
'2012/01/01' || true
'2013/11/06' || false
'2014/01/01' || true
}
// Mimic special day implementation
static private boolean isSpecialDay(Date date) {
// Check if it is the first day of month
return date[Calendar.DAY_OF_MONTH] == 1
}
}
这是一个使用我在上面暗示的组合技巧的例子:
@Grab(group='joda-time', module='joda-time', version='2.9')
@Grab(group='org.spockframework', module='spock-core', version='1.0-groovy-2.4')
import spock.lang.*
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
class TestSpecialDate extends Specification {
@Shared def zoneCombinations = [
DateTimeZone.availableIDs,
[[date:'2010/01/07', special:false], [date:'2011/01/01', special:true], [date:'2012/01/01', special:true],
[date:'2013/11/06', special:false], [date:'2014/01/01', special:true]]]
.combinations { a, b -> [zone:a, date:b.date, special:b.special] }
@Unroll
def "#date for #zone should be special #special"() {
expect:
// get current moment in default time zone
DateTime dt = new DateTime( Date.parse( 'yyyy/MM/dd', date ) )
// translate to local date time
DateTime dtLocal = dt.withZone( DateTimeZone.forID( zone ) )
// Get Java Date and assert
isSpecialDay( dtLocal.toDate() ) == special
where:
date << zoneCombinations.date
special << zoneCombinations.special
zone << zoneCombinations.zone
}
// Mimic special day implementation
static private boolean isSpecialDay(Date date) {
// Check if it is the first day of month
return date[Calendar.DAY_OF_MONTH] == 1
}
}
在 groovy 控制台中执行时,运行:
JUnit 4 Runner, Tests: 2915, Failures: 0, Time: 351
2915 次测试:-)