I have a Spock spec for testing a method that takes a 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...
}
I want to ensure that TimeZone doesn't make a difference in my method implementation (i.e. Jan 1st, 2011 is special regardless if I'm in EST or GMT or whatever). Is there a way I can repeatedly execute the test method in a single run with a different, default timezone per execution?
I could add a third column to the "where" block for the TimeZone, but that extra dimension would make the table too big for my liking.
Currently, I'm setting a random default per test run, but I don't like the fact that my test is not repeatable and, if there's a failure, the problematic TimeZone isn't captured in the assertion message.
@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)
}
Here's an example using the combinations trick I hinted at above:
@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
}
}
When executed in the groovy console, that runs:
JUnit 4 Runner, Tests: 2915, Failures: 0, Time: 351
2915 tests :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With