Create soft assertion sample and fix bugs it exposed

This commit is contained in:
Brian Norman
2020-09-27 15:14:22 -05:00
parent c91ca0d900
commit 5dac80c5dd
4 changed files with 94 additions and 25 deletions
+7 -1
View File
@@ -57,5 +57,11 @@ kotlin {
}
configure<com.bnorm.power.PowerAssertGradleExtension> {
functions = listOf("kotlin.assert", "kotlin.test.assertTrue", "kotlin.require")
functions = listOf(
"kotlin.assert",
"kotlin.test.assertTrue",
"kotlin.require",
"com.bnorm.power.AssertScope.assert",
"com.bnorm.power.assert"
)
}
@@ -0,0 +1,47 @@
package com.bnorm.power
import kotlin.contracts.*
typealias LazyMessage = () -> Any
interface AssertScope {
fun assert(assertion: Boolean, lazyMessage: LazyMessage? = null)
}
@OptIn(ExperimentalContracts::class)
fun assert(assertion: Boolean, lazyMessage: LazyMessage? = null) {
contract { returns() implies assertion }
if (!assertion) {
throw AssertionError(lazyMessage?.invoke()?.toString())
}
}
private class SoftAssertScope : AssertScope {
private val assertions = mutableListOf<Throwable>()
override fun assert(assertion: Boolean, lazyMessage: LazyMessage?) {
if (!assertion) {
assertions.add(AssertionError(lazyMessage?.invoke()?.toString()))
}
}
fun close(exception: Throwable? = null) {
if (assertions.isNotEmpty()) {
val base = exception ?: AssertionError("Multiple failed assertions")
for (assertion in assertions) {
base.addSuppressed(assertion)
}
throw base
}
}
}
@OptIn(ExperimentalContracts::class)
fun <R> assertSoftly(block: AssertScope.() -> R): R {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
val scope = SoftAssertScope()
val result = runCatching { scope.block() }
scope.close(result.exceptionOrNull())
return result.getOrThrow()
}
@@ -29,4 +29,22 @@ class PowerAssertTest {
fun require() {
require(Person.UNKNOWN.size == 1)
}
@Test
fun softAssert() {
val unknown: List<Person>? = Person.UNKNOWN
assert(unknown != null)
assert(unknown.size == 2)
val jane: Person
val john: Person
assertSoftly {
jane = unknown[0]
assert(jane.firstName == "Jane")
assert(jane.lastName == "Doe") { "bad jane last name" }
john = unknown[1]
assert(john.lastName == "Doe" && john.firstName == "John") { "bad john" }
}
}
}