Hey there, I've created some extension functions t...
# kotest-contributors
a
Hey there, I've created some extension functions to make testing time a little easier, using kotest Essentially, it enables the following:
Copy code
// BACKWARD time - defaults to 'ZonedDateTime.now()'
createdAt shouldBeWithinLast Duration.ofSeconds(1)

// FORWARD time - defaults to 'ZonedDateTime.now()'
deletedAt shouldBeWithinNext Duration.ofHour(1)


// BACKWARD time - setting custom 'base' time
val yesterdayAtNoon = ZonedDateTime.now()
        .minusDays(1)
        .with(LocalTime.of(12, 0)   
updatedAt shouldBeWithin Duration.ofDay(1) from yesterdayAtNoon

// FORWARD time - setting custom 'base' time
val tomorrowAtNoon = ZonedDateTime.now()
        .plusDays(1)
        .with(LocalTime.of(12, 0)   
updatedAt shouldBeWithin Duration.ofDay(1) to tomorrowAtNoon
What do you folks think? I'm happy to open a PR to bring it in. Not quite sure which package it should go in though
Also includes some internal util functions to make the output simpler to read:
Copy code
Expected time (2024-09-15T18:53:03.060038Z) to be within 1 milliseconds to now, but the difference was 167 milliseconds
e
Iirc we already have the equivalent of those 🤔
a
oh.. really? I couldn't find it when I was searching around 😂
I needed it to test some specific integration code where I don't know some values when invoking an API I would have used it if I had known it existed
e
Image from iOS.jpg
a
Could you link sorry? I don't see it on https://kotest.io/docs/
e
Kinda similar at least 🙂
a
Ah.. yeah found it now
Copy code
createdAt plusOrMinus 10.days
I guess I didn't notice the
plusOrMinus
because I was expecting
should
as a prefix
The only difference is that
plusOrMinus
doesn't allow you to specify another base time to compare against But that might not be super useful I guess
ohh.. I see now It's a chain actually
Copy code
createdAt shouldBe now plusOrMinus 1.seconds
Where now =
ZonedDateTime.now()
I didn't understand that. And was confused why it was always passing
e
Yeah 👍
a
I guess it's tricky to make that a compilation error, as
Copy code
createdAt plusOrMinus 1.seconds
is syntactically correct Perhaps it's just that I'm new to Kotlin 😄 (as you can maybe tell from my old Java usage of
Duration.ofSeconds
)
e
👀 1
a
Would you be happy to accept a contribution that added a default for
now
as a helper? A lot of my comparisons are against
now
so repeating
Copy code
createdAt shouldBe now plusOrMinus 1.seconds
Vs something like
Copy code
createdAt shouldBe nowPlusOrMinus 1.seconds
(Happy to take suggestions on naming!)
e
If it’s a general pattern, sure. Can you find more usages of
now plusOrMinus
with a GitHub search for instance?
a
hmm Sadly not much (all our usage is in private repos for my company) I see this, which is maybe like it? There is this one which is almost exactly like my usage But other than that, my query isn't turning up much 😓
Copy code
"shouldBe" "now" " plusOrMinus" language:Kotlin
I'm happy to just keep it as an internal (to our codebase) extension function if you'd prefer
Using
Copy code
infix fun ZonedDateTime.nowPlusOrMinus(duration: Duration): ZonedDateTimeToleranceMatcher =
    this shouldBe ZonedDateTime.now(this.zone) plusOrMinus(duration)
in our code now 👍
e
I’ll do a search across my client’s private repos as well..
🙌 1
a
@Emil Kantis sorry for following up, but just want to make sure I'm doing this correctly
Copy code
createdAt shouldBe now plusOrMinus 1.seconds
Am I using this wrong?
Copy code
io.kotest.assertions.AssertionFailedError: expected:<2024-09-15T19:58:14.160949Z> but was:<2024-09-15T19:58:13.974671Z>
By my maths, they're ~ 0.1 second from each other?
e
Hmm, wonder if it’s getting silently “discarded” due to functions being applied left to right..
Add parens around now plusorminus 1..
⚙️ 1
a
Yeap, that worked
Copy code
createdAt shouldBe (now plusOrMinus 1.seconds)
e
What’s the signature of plusOrMinus? Feels odd that it can be applied to the result of shouldBe.. but I guess shouldBe returns the left-hand operand which is also compatible..
a
That's just the default kotest - not anything I've modified so
Copy code
infix fun ZonedDateTime.plusOrMinus(tolerance: Duration): ZonedDateTimeToleranceMatcher =
   ZonedDateTimeToleranceMatcher(this, tolerance)
e
We should probably add JSR305
@CheckReturnValue
on plusOrMinus to avoid that.. since it only works with JVM types, it should be fine to use the JVM-only annotation
💯 1
👌 1
a
hmm. I added that as a quick temporary function, but it still failed
Copy code
@CheckReturnValue
infix fun ZonedDateTime.plusOrMinus(tolerance: Duration): ZonedDateTimeToleranceMatcher =
   ZonedDateTimeToleranceMatcher(this, tolerance)
Am I just using the function incorrectly?
hmm. I think I know the issue I will try making a small test case in my kotest fork and see if I can replicate there
a
We should describe this parenthesis thing in the docs