Spock - 使用不同的系统默认值重复测试

时间:2015-11-06 20:09:38

标签: unit-testing groovy timezone spock

我有一个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或其他什么)。 有没有办法可以在一次运行中重复执行测试方法,每次执行时使用不同的默认时区?

我可以在TimeZone的“where”块中添加第三列,但是这个额外的维度会使表格太大而不符合我的喜好。

目前,我在每个测试运行中设置一个随机默认值,但我不喜欢我的测试不可重复这一事实,如果发生故障,则在断言消息中不会捕获有问题的TimeZone。 / p>

@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)
}

2 个答案:

答案 0 :(得分:5)

这是一个使用我在上面提到的组合技巧的例子:

@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测试: - )

答案 1 :(得分:3)

使用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
    }
}