https://kotlinlang.org logo
#kotest
Title
# kotest
o

Oliver.O

08/29/2021, 8:53 PM
Is a
suspend
version of
shouldThrow
missing for a reason or should I file an issue?
s

sam

08/29/2021, 10:43 PM
Is shouldThrow inline ?
l

LeoColman

08/30/2021, 1:18 AM
I think it is, yes
We had some issues with that a lot of time ago, in which
x = y
couldn't be inlined by our function, and then we added
shouldThrowUnit
. I believe all of this is inline
s

sam

08/30/2021, 4:27 AM
If it's inline then it will work for suspend too
o

Oliver.O

08/30/2021, 10:45 AM
Indeed it is, I'll investigate further.
Still investigating... Had to deal with this one first: https://github.com/kotest/kotest/issues/2447
s

sam

08/31/2021, 2:36 PM
Nice find. I'd like to introduce coroutine based versions of these for 5.0
j

Jim

08/31/2021, 4:17 PM
Ah, y'all are in here
I'm thinking
TestExecutionFilter
that installs the necessary stuff for withClue. Then deprecate the old ones and make withClue a suspending extension function on TestContext
o

Oliver.O

08/31/2021, 4:30 PM
Hmm, in that case
withClue
would no longer be usable with the standalone assertions-package, (i.e. without the Kotest framework), right?
j

Jim

08/31/2021, 4:31 PM
Hmmm, we could have a version that is an extension on CoroutineContext too that just hooks up the necessary state if it hasn’t been set up in the TestExecutionFilter
o

Oliver.O

08/31/2021, 5:47 PM
I had just envisioned something like this:
Copy code
private val _errorCollector = ThreadLocal<ThreadLocalErrorCollector>()
val errorCollector: ErrorCollector get() = _errorCollector.get()
    
suspend fun withErrorCollector(thunk: suspend () -> R) = withContext(_errorCollector.asContextElement()) { thunk() }

suspend fun <R> withClue(clue: Any?, thunk: suspend () -> R): R {
    try {
        errorCollector.pushClue { clue.toString() }
        return withErrorCollector { thunk() }
    } finally {
        errorCollector.popClue()
    }
}
j

Jim

08/31/2021, 5:48 PM
well that is simpler 🤣
I’ll have to think about how that works across multiple
withClue
,
any
,
all
, and
one
o

Oliver.O

08/31/2021, 5:51 PM
Yes, the above is pretty preliminary stuff. It also needs some additional thinking on how to bridge coroutines and non-coroutines land.
j

Jim

08/31/2021, 5:57 PM
The current implementation seems fine for non-coroutines land I think, right? So probably dual implementations
o

Oliver.O

08/31/2021, 7:25 PM
Yes, in an ideal universe, the same invocation would work in both worlds. However, the compiler does not like type inference based on
suspend
differences alone:
Copy code
suspend fun <R> withClue(clue: Any?, thunk: suspend () -> R): R

fun <R> withClue(clue: Any?, thunk: () -> R): R
In this case, it would complain on the non-suspending call site:
Overload resolution ambiguity
This is https://youtrack.jetbrains.com/issue/KT-23610. Another point: You start in non-coroutine land, invoke
withClue
(or
assertSoftly
) there, then start coroutines which might switch threads. You'd probably have to make the ThreadLocalErrorCollector from non-coroutine land available to coroutines.
5 Views